什么是Sphinx/Coreseek

Sphinx是一个在GPLv2下分发的全文检索引擎;Coreseek是一个可供企业使用的、基于Sphinx(可独立于Sphinx原始版本运行)的中文全文检索引擎,按照GPLv2协议发行,商业使用(例如嵌入到其他程序中)需要联系我们以获得商业授权。

一般而言,Sphinx是一个独立的全文搜索引擎;而Coreseek是一个支持中文的全文搜索引擎,意图为其他应用提供高速、低空间占用、高结果相关度的中文全文搜索能力。Sphinx/Coreseek可以非常容易的与SQL数据库和脚本语言集成。

当前系统内置MySQLPostgreSQL 数据库数据源的支持,也支持从管道标准输入读取入特定格式的XML数据。通过修改源代码,用户可以自行增加新的数据源(例如:其他类型的DBMS的原生支持)。在最新的版本中,用户还可以使用Python脚本作为数据源来获取任何已知世界和未知世界的数据,这极大的扩展了数据源的来源。

搜索API支持PHPPythonPerlRudyJava,并且也可以用作MySQL存储引擎。搜索API非常简单,可以在若干个小时之内移植到新的语言上。

Sphinx SQL PhraseIndex的缩写,但不幸的和CMUSphinx项目重名。

Coreseek  http://www.coreseek.cn Sphinx在中国地区的用户提供支持服务.   

Sphinx  http://sphinxsearch.com/               

 

Sphinx/Coreseek 的特性

  • 高速的建立索引(在当代CPU上,峰值性能可达到10MB/);

  • 高性能的搜索(2 – 4GB 的文本数据上,平均每次检索响应时间小于0.1);

  • 可处理海量数据(目前已知可以处理超过100GB的文本数据在单一CPU的系统上可处理100 M 文档);

  • 提供了优秀的相关度算法,基于短语相似度和统计(BM25)的复合Ranking方法;

  • 支持分布式搜索;

  • 提供文档片段(摘要以及高亮)生成功能;

  • 可作为MySQL的存储引擎提供搜索服务;

  • 支持布尔、短语、词语相似度等多种检索模式;

  • 文档支持多个全文检索字段(缺省配置下,最大不超过32);

  • 文档支持多个额外的属性信息(例如:分组信息,时间戳等);

  • 停止词查询;

  • 支持单一字节编码和UTF-8编码,以及对GBKBIG5的完善支持;

  • 支持英语、俄语词词干化和Soundex,以便进行词形学处理;

  • 原生的MySQL支持(同时支持MyISAM InnoDB );

  • 原生的PostgreSQL支持;

  • 支持直接模拟为MySQL服务端运行;

  • 支持MMSeg分词引擎,用户可自定义词典;

  • Python数据源支持,得以获取任何已知世界和未知世界的数据.

目前,Sphinx/Coreseek的发布包包括如下软件:

  • indexer: 用于创建全文索引;

  • search: 一个简单的命令行(CLI) 的测试程序,用于测试全文索引;

  • searchd: 一个守护进程,其他软件可以通过这个守护进程进行全文检索;

  • sphinxapi: 一系列searchd 的客户端API 库,用于流行的Web脚本开发语言(PHP, Python, Perl, Ruby, Java).

  • spelldump: 一个简单的命令行工具,用于从 ispell  MySpell (OpenOffice内置绑定格式的字典中提取词条。当使用 wordforms 时可用这些词条对索引进行定制.

  • indextool: 工具程序,用来转储关于索引的多项调试信息。此工具是从版本Coreseek 3.1(Sphinx 0.9.9-rc2)开始加入的。

  • mmseg: 工具程序和库,Coreseek用于提供中文分词和词典处理。

安装前准备环境

yum install make gcc g++ gcc-c++ libtool make mysql-devel libxml2-devel expat-devel 

官网参考地址:http://www.coreseek.cn/products/products-install/install_on_bsd_linux/RHEL5-5/


来到官网http://www.coreseek.com/下载Coreseek 3.2.14稳定版,解压进入目录。

# tar xf coreseek-3.2.14.tar.gz

# cd coreseek-3.2.14

配置语言支持中文

# export LANG="zh_CN.UTF-8"

# export LC_ALL="zh_CN.UTF-8"

# cat testpack/var/test/test.xml

wKiom1R-i4bgy4L2AAGxpagGNaw469.jpg

安装coreseek开发的mmseg,为coreseek提供中文分词功能

# cd mmseg-3.2.14/

# ./bootstrap

# ./configure --prefix=/usr/local/mmseg3

# make && make install

中文分词测试

# /usr/local/mmseg3/bin/mmseg -d /usr/local/mmseg3/etc src/t1.txt

 

中文/x /x /x 测试/x

中国人/x 上海市/x

 

Word Splite took: 0 ms.

安装coreseek

# cd csft-3.2.14/

# sh buildconf.sh

1
. /configure  --prefix= /alidata/server/sphinx/coreseek  --without-python --without-unixodbc --with-mmseg --with-mmseg-includes= /alidata/server/sphinx/mmseg3/include/mmseg  --with-mmseg-libs= /alidata/server/sphinx/mmseg3/lib/  --with-mysql= /alidata/server/mysql   --with-mysql-includes= /alidata/server/mysql/include/

# make && make install

测试是否可以正常运行

# /usr/local/coreseek/bin/indexer -c /usr/local/coreseek/etc/sphinx-min.conf.dist

wKioL1R-jGuw-AWdAAFTJpw38mI702.jpg

csft-4.0版显示:ERROR: nothing to do.


coreseek中文全文检索测试

# cd testpack/

# /usr/local/coreseek/bin/indexer -c etc/csft.conf

wKiom1R-jEfDtn-DAAEXq729j_8678.jpg

索引全部数据

# /usr/local/coreseek/bin/indexer -c etc/csft.conf -all

wKioL1R-jcrxJ2dNAAG8p9tFa-I285.jpg

索引指定数据

# /usr/local/coreseek/bin/indexer -c etc/csft.conf xml

wKiom1R-kE2BkFSPAAGH6upCW9M497.jpg

测试搜索

# /usr/local/coreseek/bin/search -c etc/csft.conf

wKiom1R-kM_gwWq9AAFuX0pLqho609.jpg

测试搜索关键词

# /usr/local/coreseek/bin/search -c etc/csft.conf -a hello欢迎来到北京清华大学

wKiom1R-kQ_z2PkyAAFde5WUkvA847.jpg

开启搜索服务

# /usr/local/coreseek/bin/searchd -c etc/csft.confwKioL1R-kcbxxTyPAAGDtENOrVE686.jpg

如要已启动服务,要更新索引,请使用 /usr/local/coreseek/bin/indexer-c etc/csft.conf --all --rotate

如要停止搜索服务,请使用 /usr/local/coreseek/bin/searchd-c etc/csft.conf --stop

 

然后,请参考csft-3.2.14api目录中的相关文件,使用PHPPythonRubyJava来测试搜索服务;也可以前往< ahref="/products-install/step_by_step/">搜索服务建立三步曲,查看第三步使用PHP测试。

 

通过以上步骤,coreseek已经安装测试完成,可以提供正常的xml数据源索引以及提供对应的搜索服务了,下一步工作,请查看手册,准备好mysql数据信息,以及进行mysql数据源的测试,并在您的应用中调用搜索服务;mysql数据源的配置可参考testpack/etc/csft_mysql.conf文件


官方文档地址:http://www.coreseek.cn/docs/coreseek_3.2-sphinx_0.9.9.html

快速安装地址:http://www.coreseek.cn/product_install/install_on_bsd_linux/#mysql

在实现以上功能之后,即可开始下面的实验。


LAMP+Coreseek+sphinx构建中文检索引擎

安装好LAMP环境,并将它们启动(),在前面的文章中都有讲到。


1、  先给数据库插入一些数据,用于测试,在解压coreseek源码包后可以在/coreseek-4.1-beta/testpack/var/test/找到.sql的数据库脚本文件,导入数据库即可。

 

2、  安装PHPsphinx扩展

可以在这里(http://pecl.php.net/package/sphinx)找到sphinxphp扩展源码,注意,使用phpizeconfigure的时候可能会要求要安装libsphinxclient,它在coreseek-4.1-beta/csft-4.1/api/libsphinxclient/里面能找到,编译安装它以后就可以configuremake,生成动态so文件了。

 

3、  给服务提供配置文件 (源码目录下有样例:  /coreseek-4.1-beta/testpack/etc/csft_mysql.conf

#源定义

source study

{

        type                                    = mysql


        sql_host                                = localhost

        sql_user                                = root

        sql_pass                                =

        sql_db                                  = test

        sql_port                                = 3306

        sql_query_pre                   = SET NAMES utf8


        sql_query                               = select id,title,content,group_id from documents;

// 这里使用select 将想要被用于检索的索引字段查出来,缓存于Sphinx服务器中,sql_query第一列id需为整数,titlecontent作为字符串/文本字段,被全文索引

        sql_query_info                  = SELECT * FROM documents where id=$id  

 #仅被命令行搜索所用,用来获取和显示文档信息,目前仅对MySQL有效,且仅用于调试目的。此查询为每个文档ID获取CLI搜索工具要显示的文档信息。它需要包含$id宏,以此来对应到查询的文档的ID

}


#index定义

index study

{

        source                  = study             #对应的source名称

        path                    = /usr/local/coreseek/var/data/study

        docinfo                 = extern

        mlock                   = 0

        morphology              = none   //不使用任何词形处理器

        min_word_len            = 1      //最小索引词长度。可选选项,默认为1(索引任何词

        html_strip                              = 0

        charset_dictpath = /usr/local/mmseg3/etc/    //设置中文分词词典所在的目录

        #charset_dictpath = etc/        

        charset_type            = zh_cn.utf-8

}

source mysql

{

        type                                    = mysql


        sql_host                                = localhost

        sql_user                                = root

        sql_pass                                =

        sql_db                                  = tuchao

        sql_port                                = 3306

        sql_query_pre                   = SET NAMES utf8


        sql_query                               = SELECT id, title, abstract FROM ic_video

                                                                                     

        sql_query_info                  = SELECT * FROM ic_video where id=$id  

}



index mysql

{

        source                  = mysql            

        path                    = /usr/local/coreseek/var/data/mysql

        docinfo                 = extern

        mlock                   = 0

        morphology              = none

        min_word_len            = 1

        html_strip                              = 0

        charset_dictpath = /usr/local/mmseg3/etc/  

        #charset_dictpath = etc/   

        charset_type            = zh_cn.utf-8

}

source qupeiyin

{

        type                                    = mysql


        sql_host                                = localhost

        sql_user                                = root

        sql_pass                                =

        sql_db                                  = tuchao2

        sql_port                                = 3306

        sql_query_pre                   = SET NAMES utf8


        sql_query                               = SELECT id, title, description FROM course

                                                                                    

        sql_query_info                  = SELECT * FROM course where id=$id  

}


index qupeiyin

{

        source                  = qupeiyin  

        path                    = /usr/local/coreseek/var/data/qupeiyin

        docinfo                 = extern

        mlock                   = 0

        morphology              = none

        min_word_len            = 1

        html_strip                              = 0

        charset_dictpath = /usr/local/mmseg3/etc/  

        #charset_dictpath = etc/  

        charset_type            = zh_cn.utf-8

}


#全局index定义

indexer

{

        mem_limit                       = 128M    //索引过程内存限制,indexer不会超越的强制内存限制,设置太低会影响索引速度,一般为256M~1024M,最大限制是2048M.

}


#searchd服务定义

searchd

{

    listen                  =   9312

        read_timeout            = 5  //网络客户端请求的读超时时间, searchd 强制关闭在此时间内未能成功发出查询的客户端连接。

        max_children            = 30  //子进程的最大数量,任何时候不可能有比此设置值更多的搜索同时运行。当达到限制时,新的输入客户端会被用临时失败(SEARCH_RETRY)状态码驳回;

        max_matches                     = 1000   //为每个索引所保持并返回给客户端的匹配数目的最大值

        seamless_rotate         = 1                          //启用无缝轮换,数据轮换时不暂停搜索服务。

        preopen_indexes         = 0

        unlink_old                      = 1    //索引轮换成功之后,是否删除以.old为扩展名的索引拷贝。可选选项,默认为1(删除这些索引拷贝)。

        pid_file = /usr/local/coreseek/var/log/searchd_mysql.pid

        log = /usr/local/coreseek/var/log/searchd_mysql.log

        query_log = /usr/local/coreseek/var/log/query_mysql.log

}

在写配置文件的时候,sourece名称可以与index名称不一样,但是path后的名称一定要和index定义的名称一致。

4、提供服务启动脚本


#!/bin/bash

# searchd - this script start and stop the searchd daemon

#

# chkconfig - 85 20

# description: 

#

# processname: searchd

# config:  /usr/local/coreseek/etc/csft_mysql.conf

. /etc/rc.d/init.d/functions


searchd="/usr/local/coreseek/bin/searchd"

prog=$(basename $searchd)

conf_file="/usr/local/coreseek/etc/csft_mysql.conf"

lockfile="/var/lock/subsys/searchd"


start() {

    [ -e $lockfile ] && echo "searchd is already start" && exit 0

    [ -x $searchd ] || exit 1

    [ -f $conf_file ] || exit 2

    echo -n "Starting $prog:"

    daemon $searchd -c $conf_file

    retval=$?

    echo

    if [ $retval -eq 0 ]; then

       touch $lockfile

    else

        echo "$prog is starting failed"

    fi

        return $retval

}

stop() {

    echo -n $"Stopping $prog:"

    killproc $prog -QUIT

    retval=$?

    echo

    if [ $retval -eq 0 ]; then

       rm -rf $lockfile

    fi

        return $retval

}


restart() {

stop

sleep 1

start

}


indexer() {

/usr/local/coreseek/bin/indexer -c $conf_file --all


}


case "$1" in

        start)

             start

             ;;

        stop)

            stop

            ;;

        restart)

            restart

            ;;

        indexer)

           indexer

            ;;

        *)

           echo "Usage:$0 {start|stop|restart|indexer}"

           exit 2

esac


5、  重建全部索引

# /etc/init.d/searchd indexer

wKioL1SVGm_C--PGAAGBaCYcCW8559.jpg

6、  启动searchd服务

# service searchd start

wKiom1SVGfCCWZAkAAG2-9Ntc5o667.jpg


7、  提供PHP测试程序

<?php

$s = new SphinxClient;

$s->setServer("localhost", 9312);

$s->setArrayResult(true);

$s->setSelect();

$s->setMatchMode(SPH_MATCH_ALL);

//SPH_MATCH_ALL这个检索方法表示只显示匹配到的数据ID,并进行分词。SPH_MATCH_ANY表示先将搜索的内容进行分词,输出每个分词匹配到的数据ID

$result1 = $s->query('乔布斯','mysql');

$result2 = $s->query('搞笑','qupeiyin');

$result3 = $s->query('Google','study');

print_r($result1);

print_r($result2);

print_r($result3);

?>


8、测试服务

    我可以在httpd服务器指定的目录下创建一个test.php拷贝以上代码,根据自己的数据库数据做更改后保存。

这一句我要讲下$result1 = $s->query('乔布斯','mysql');  “乔布斯是搜索的关键词,后面的’mysql ’对应的是定义在csft_mysql.conf中的索引名称。表示从哪个索引中找

 

以下是用浏览器访问test.php返回的结果:

wKioL1SVHA3zks_OAALbYkfToLo666.jpg

    首先返回结果是在mysql索引中搜索关键词乔布斯’ 的,可以看到在id=>38 id=>39  有匹配到,而且对搜集内容进行了分词。

[matches] => Array ( [0] => Array ([id] => 38 [weight] => 6 [attrs] => Array ( ) ) [1] => Array ( [id]=> 39 [weight] => 3 [attrs] => Array ( ) ) ) [total] => 2 [total_found]=> 2 [time] => 0.002 [words] => Array ( [] =>Array ( [docs] => 2 [hits] => 3 ) [] => Array ([docs] => 2 [hits] => 3 ) [] => Array ( [docs] => 2 [hits] => 3 ) ) )

 

我们上MySQL服务器查找对应ID来验证:

wKiom1SVG6yCXgugAAQlK5NWBiE542.jpg


    我们再分析后续的输出结果,在qupeiyin索引中搜索‘ 搞笑’ 关键词,这里可以看到在id=>29  id=>518  有匹配到.

Array ( [error] => [warning] =>[status] => 0 [fields] => Array ( [0] => title [1] => description )[attrs] => Array ( ) [matches] => Array ( [0] => Array ( [id] => 29 [weight] => 1 [attrs] => Array () ) [1] => Array ( [id] => 518 [weight]=> 1 [attrs] => Array ( ) ) ) [total] => 2 [total_found] => 2[time] => 0.002 [words] => Array ( [搞笑] => Array ([docs] => 2 [hits] => 2 ) ) )

 

我们再来到数据库验证:

wKiom1SVHAni20lhAAI7IldQj_M848.jpg


wKioL1SVHLyAsyxwAAKuxXjR0SA840.jpg


第三个输出也是可以找到对应的数据的,笔者就不上图了,由此可以看出,在对应的ID号确实能找到匹配的数据。