sphinx的安装配置和中文分词包coreseek

时间:2021-10-10 08:23:00

sphinx在此处下载:

http://sphinxsearch.com/downloads/release/

本次我下的是2.2.4版本


自持中文分词的包叫做coreseek,其实就是带了中文分词插件的sphinx,在此处下载:

http://www.coreseek.cn/

本次我下的是稳定版3.2.14


先写个结论,sphinx本身是可以支持中文搜索的,只是不支持中文分词,需要安装中文分词插件,coreseek就是一个打包了mmseg中文分词插件和sphinx源码的安装包

目前coreseek已经很久不更新了,稳定版3.2.14内带的的sphinx还是 0.9.9 release版本的;而sphinx可以通过设置为“一元切分模式”来支持搜索中文

在实际使用中,搜索非中文的话,sphinx比coreseek要快;搜索短中文字符串的话,开启了“一元切分模式”的sphinx比coreseek要快;只有在搜索长中文字串时,coreseek的分词优势才能显现,比sphinx要快

所以根据你的应用场景来选择用哪个,如果是索引英文、数字、字符较多的数据,就用源生sphinx;如果是索引中文非常多非常长的数据,还是用coreseek吧


下面先来讲sphinx的安装和配置:

把包下载下来,我下的是http://sphinxsearch.com/files/sphinx-2.2.4-release.tar.gz

tar xzvf sphinx-2.2.4-release.tar.gz

cd sphinx-2.2.4-release

./configure --prefix=/usr/local/sphinx/   --with-mysql  --enable-id64 #如果是64位的才加这个选项

make

make install


这样就装好了,现在来配置

cp /usr/local/sphinx/etc/sphinx-min.conf.dist /usr/local/sphinx/etc/test.conf

vim /usr/local/sphinx/etc/test.conf

1.   sphinx配置文件结构介绍

Sphinx的配置文件结构如下:

Source 源名称1{     

#添加数据源,这里会设置一些连接数据库的参数比如数据库的IP、用户名、密码等

#设置sql_query、设置sql_query_pre、设置sql_query_range等后面会结合例子做详细介绍

 ……

}

Index 索引名称1{

     Source=源名称1

#设置全文索引

     ……

}

Indexer{

#设置Indexer程序配置选项,如内存限制等

……

}

Searchd{  

#设置Searchd守护进程本身的一些参数

……

}

Source和Index都可以配置多个。

 

2.   spinx配置案例详细解释

接下来就来针对一个配置案例来做详细的配置介绍:

#定义一个数据源

source search_main

{

           #定义数据库类型

   type                 = mysql

           #定义数据库的IP或者计算机名

   sql_host             = localhost

           #定义连接数据库的帐号

   sql_user             = root

           #定义链接数据库的密码

   sql_pass             = test123

           #定义数据库名称

   sql_db               = test

           #定义连接数据库后取数据之前执行的SQL语句

   sql_query_pre        = SET NAMESutf8

   sql_query_pre        = SET SESSIONquery_cache_type=OFF

           #创建一个sph_counter用于增量索引

   sql_query_pre        = CREATETABLE IF NOT EXISTS sph_counter \

                                      ( counter_id INTEGER PRIMARY KEY NOTNULL,max_doc_id INTEGER NOT NULL)

           #取数据之前将表的最大id记录到sph_counter表中

   sql_query_pre        = REPLACEINTO sph_counter SELECT 1, MAX(searchid) FROM v9_search

           #定义取数据的SQL,第一列ID列必须为唯一的正整数值

    sql_query            = SELECTsearchid,typeid,id,adddate,data FROM v9_search where \

                                      searchid<(SELECT max_doc_id FROM sph_counter WHERE counter_id=1 ) \

                                        andsearchid>=$start AND searchid<=$end

           #sql_attr_uint和sql_attr_timestamp用于定义用于api过滤或者排序,写多行制定多列

   sql_attr_uint        = typeid

   sql_attr_uint        = id

   sql_attr_timestamp   = adddate

           #分区查询设置

   sql_query_range      = SELECTMIN(searchid),MAX(searchid) FROM v9_search

           #分区查询的步长

   sql_range_step       = 1000

           #设置分区查询的时间间隔

   sql_ranged_throttle  = 0

           #用于CLI的调试

   sql_query_info       = SELECT *FROM v9_search WHERE searchid=$id

}

#定义一个增量的源

source search_main_delta : search_main

{

   sql_query_pre       = set namesutf8

           #增量源只查询上次主索引生成后新增加的数据

#如果新增加的searchid比主索引建立时的searchid还小那么会漏掉

   sql_query           = SELECTsearchid,typeid,id,adddate,data FROM v9_search where  \

                                  searchid>(SELECT max_doc_id FROM sph_counter WHERE counter_id=1 ) \

                                   andsearchid>=$start AND searchid<=$end

   sql_query_range     = SELECTMIN(searchid),MAX(searchid) FROM v9_search where \

                                       searchid>(SELECT max_doc_id FROM sph_counter WHERE counter_id=1 )

}

 

#定义一个index_search_main索引

index index_search_main

{

           #设置索引的源

   source            = search_main

           #设置生成的索引存放路径

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

           #定义文档信息的存储模式,extern表示文档信息和文档id分开存储

   docinfo           = extern

           #设置已缓存数据的内存锁定,为0表示不锁定

   mlock             = 0

           #设置词形处理器列表,设置为none表示不使用任何词形处理器

   morphology        = none

           #定义最小索引词的长度

   min_word_len      = 1

           #设置字符集编码类型,我这里采用的utf8编码和数据库的一致

   charset_type      = zh_cn.utf-8

           #指定分词读取词典文件的位置

   charset_dictpath  =/usr/local/mmseg3/etc

           #不被搜索的词文件里表。

   stopwords       =/usr/local/coreseek/var/data/stopwords.txt

           #定义是否从输入全文数据中取出HTML标记

   html_strip       = 0

}

#定义增量索引

index index_search_main_delta : index_search_main

{

   source   = search_main_delta

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

}

 

#定义indexer配置选项

indexer

{

           #定义生成索引过程使用索引的限制

   mem_limit        = 512M

}

 

#定义searchd守护进程的相关选项

searchd

{

           #定义监听的IP和端口

   #listen            = 127.0.0.1

   #listen            =172.16.88.100:3312

    listen            = 3312

    listen            = /var/run/searchd.sock

           #定义log的位置

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

           #定义查询log的位置

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

           #定义网络客户端请求的读超时时间

   read_timeout       = 5

           #定义子进程的最大数量

   max_children       = 300

           #设置searchd进程pid文件名

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

           #定义守护进程在内存中为每个索引所保持并返回给客户端的匹配数目的最大值

   max_matches        = 100000

           #启用无缝seamless轮转,防止searchd轮转在需要预取大量数据的索引时停止响应

    #也就是说在任何时刻查询都可用,或者使用旧索引,或者使用新索引

   seamless_rotate    = 1

           #配置在启动时强制重新打开所有索引文件

   preopen_indexes    = 1

           #设置索引轮转成功以后删除以.old为扩展名的索引拷贝

   unlink_old         = 1

           # MVA更新池大小,这个参数不太明白

   mva_updates_pool   = 1M

           #最大允许的包大小

   max_packet_size    = 32M

           #最大允许的过滤器数

   max_filters        = 256

           #每个过滤器最大允许的值的个数

   max_filter_values  = 4096

}


综合上面的资料,我对test.conf作了如下配置:

source message1
{
        type                    = mysql

        sql_host                = 127.0.0.1
        sql_user                = root
        sql_pass                = 123456
        sql_db                  = yh_comment
        sql_port                = 3308  # optional, default is 3306

        sql_query_pre           = SET NAMES utf8
        sql_query               = \
                SELECT id,bid,uid,content,valid,createtime \
                FROM tbl_cmt00 \
                UNION SELECT id,bid,uid,content,valid,createtime \
                FROM tbl_cmt01 \
                UNION SELECT id,bid,uid,content,valid,createtime \
                FROM tbl_cmt02 \
                UNION SELECT id,bid,uid,content,valid,createtime \
                FROM tbl_cmt03

        sql_field_string                = bid
        sql_attr_uint           = uid
        sql_field_string        = content
        sql_attr_string         = valid
        sql_field_string        = createtime
}


index message1
{
        source                  = message1
        path                    = /usr/local/sphinx/var/data/message1
        ngram_len               = 1 #表示使用一元字符切分模式,从而得以对单个中文字符进行索引
        ngram_chars             = U+3000..U+2FA1F, U+FF41..U+FF5A->a..z, U+FF21..U+FF3A->a..z, A..Z->a..z, a..z #表示要进行一元字符切分模式的字符集
}


indexer
{
        mem_limit               = 128M
}


searchd
{
        listen                  = 9412
        log                     = /usr/local/sphinx/var/log/searchd-message1.log
        query_log               = /usr/local/sphinx/var/log/query-message1.log
        read_timeout            = 5
        max_children            = 30
        pid_file                = /usr/local/sphinx/var/log/searchd-message1.pid
        #max_matches            = 1000
        seamless_rotate         = 1
        preopen_indexes         = 1
        unlink_old              = 1
        workers                 = threads # for RT to work
        binlog_path             = /usr/local/sphinx/var/data
}


上面的配置是已经开启“一元切分模式”

具体可以参考文档http://www.coreseek.cn/products-install/ngram_len_cjk/


这样配置就完成了,接下来要生成索引和开启守护进程:

/usr/local/sphinx/bin/indexer -c /usr/local/sphinx/etc/test.conf --all

/usr/local/sphinx/bin/searchd -c /usr/local/sphinx/etc/test.conf

如果在建立索引的过程中出现”No fields in schema”的错误,原因是:sphinx对于sql数据源需要至少一个sql_field_string,当没有指定sql_field_string时会将数据源中没有明确指定为sql_attr_string的字符串字段用来做sql_field_string。当全部字符串字段设为sql_attr_string时不能建立索引,而随便注释一条sql_attr_string,或者选择一条sql_attr_string变为sql_field_string,就可以了

如果数据库更新了,需要重新建立索引,重输一遍上面简历索引的指令就行

如果重建索引时守护进程正在运行,会报错,需要运行下面的指令,会重建索引并且重开守护进程

/usr/local/sphinx/bin/indexer -c /usr/local/sphinx/etc/test.conf --all --rotate


现在进行php和sphinx的交互:

到http://pecl.php.net/package/sphinx下载php的sphinx模块,放到php中引用起来,方法不在此赘述

vim test.php


$sphinx = new SphinxClient;

//sphinx的主机名和端口

$sphinx->SetServer ( '192.168.1.168', 9412 );

$sphinx->SetConnectTimeout ( 1 );

//设置返回结果集为php数组格式
$sphinx->SetArrayResult ( true );

//匹配结果的偏移量,参数的意义依次为:起始位置,返回结果条数,最大匹配条数

$sphinx->SetLimits(0, 20, 1000);

//最大搜索时间

$sphinx->SetMaxQueryTime(10);

//索引源是配置文件中的 index 类,如果有多个索引源可使用,号隔开:'email,diary' 或者使用'*'号代表全部索引源

$index = 'message1';

//搜索关键字

$result = $sphinx->Query ( '你要搜索的非中文/中文字串', "*" );

if (!$result){
    print_r($sphinx->getLastError());
}

print_r($result);


$result是一个数组,其中

total是匹配到的数据总数量

matches是匹配的数据,包含id,attrs这些信息

words是搜索关键字的分词

接下来介绍sphinx一些类似mysql条件的用法
//id的范围
$sphinx->SetIdRange($min, $max);
 
//属性过滤,可过滤的属性必需在配置文件中设置sql_attr_    ,之前我们定义了这些
 
    sql_attr_uint            = fromid
 
    sql_attr_uint            = toid
 
    sql_attr_timestamp  = sendtime
 
//如果你想再次修改这些属性,配置完成后记得重新建立索引才能生效
 
 
 
//指定一些值
 
$sphinx->SetFilter('fromid', array(1,2));    //fromid的值只能是1或者2
 
//和以上条件相反,可增加第三个参数
 
$sphinx->SetFilter('fromid', array(1,2), false);    //fromid的值不能是1或者2
 
//指定一个值的范围
 
$sphinx->SetFilterRange('toid', 5, 200);    //toid的值在5-200之间
 
//和以上条件相反,可增加第三个参数
 
$sphinx->SetFilterRange('toid', 5, 200, false);    //toid的值在5-200以外
 
 
 
//执行搜索
 
$result = $sphinx->query('关键字', '*');


现在来讲coreseek的安装配置:

把包下载下来,我下载的地址是http://www.coreseek.cn/uploads/csft/3.2/coreseek-3.2.14.tar.gz

安装过程可以参考官网文档http://www.coreseek.cn/products-install/install_on_bsd_linux/

我直接复制过来,照着打命令就可以了

##前提:需提前安装操作系统基础开发库及mysql依赖库以支持mysql数据源和xml数据源
##安装mmseg
$ cd mmseg-3.2.14
$ ./bootstrap    #输出的warning信息可以忽略,如果出现error则需要解决
$ ./configure --prefix=/usr/local/mmseg3
$ make && make install
$ cd ..

##安装coreseek
$ cd csft-3.2.14 或者 cd csft-4.0.1 或者 cd csft-4.1
$ sh buildconf.sh    #输出的warning信息可以忽略,如果出现error则需要解决
$ ./configure --prefix=/usr/local/coreseek  --without-unixodbc --with-mmseg --with-mmseg-includes=/usr/local/mmseg3/include/mmseg/ --with-mmseg-libs=/usr/local/mmseg3/lib/ --with-mysql    ##如果提示mysql问题,可以查看MySQL数据源安装说明
$ make && make install
$ cd ..

这样就算装好了

接下来同样是配置,和sphinx有些不一样

同样是参考官网文档http://www.coreseek.cn/products-install/coreseek_mmseg/

 
#以下部分为中文分词核心配置
	#stopwords		= /path/to/stowords.txt的位置
	charset_dictpath		= /usr/local/mmseg3/etc/
	charset_type		= zh_cn.utf-8
	#charset_table                    = .................... #需将原有
的该配置注释掉
	ngram_len                    = 0
#以上部分为中文分词核心配置

关键在于:

#必须设置,表示词典文件的目录,该目录下必须有uni.lib词典文件存在

charset_dictpath=/usr/local/mmseg3/etc/

#必须设置,表示启用中文分词功能;否则中文分词功能无效,使用sphinx的其他处理模式

charset_type=zh_cn.utf-8

#必须设置,表示取消原有的一元字符切分模式,不使其对中文分词产生干扰

ngram_len=0

#charset_table的配置需要注释掉!

#charset_table=......


我的配置是

source message1
{
        type                                    = mysql

        sql_host                                = 127.0.0.1
        sql_user                                = root
        sql_pass                                = 123456
        sql_db                                  = yh_comment
        sql_port                                = 3308  # optional, default is 3306

        sql_query_pre                           = SET NAMES utf8
        sql_query_pre                           = SET SESSION query_cache_type=OFF
        sql_query                               = \
                SELECT id,bid,uid,content,valid,createtime FROM tbl_cmt00

        sql_attr_uint                   = uid

        sql_query_info                  = SELECT * FROM tbl_cmt00 WHERE id=$id
}


index message1
{
        source                                  = message1
        path                                    = /usr/local/coreseek/var/data/message1
        docinfo                                 = extern
        charset_type            = zh_cn.utf-8
        ngram_len               = 0
        charset_dictpath    = /usr/local/mmseg3/etc/
}


indexer
{
        mem_limit                               = 32M
}


searchd
{
        port                                    = 9512
        log                                             = /usr/local/coreseek/var/log/searchd-message1.log
        query_log                               = /usr/local/coreseek/var/log/query-message1.log
        read_timeout                    = 5
        max_children                    = 30
        pid_file                                = /usr/local/coreseek/var/log/searchd-message1.pid
        max_matches                             = 1000
        seamless_rotate                 = 1
        preopen_indexes                 = 0
        unlink_old                              = 1
}


现在可以尝试搜索

/usr/local/coreseek/bin/search -c /usr/local/coreseek/etc/test.conf 你要搜索的非中文/中文字串

结果应该是类似:

displaying matches:
1. document=4, weight=5, uid=3046690
        id=4
        bid=3046730-4e842acdcf8be
        uid=3046690
        content=??????????
        valid=y
        createtime=1317286728

words:
1. '没有': 683 documents, 700 hits
2. '听': 124 documents, 134 hits
3. '过': 722 documents, 741 hits
4. ',': 9797 documents, 11936 hits
5. '过来': 47 documents, 47 hits
6. '一下': 404 documents, 404 hits

coreseek和php的交互

总的来说和sphinx的交互几乎是一样的

用的是pecl的sphinx模块的话,可能$result会返回false,使用getLastError()方法会返回

client version is higher than daemon version
这样的错误

可以禁用pecl的sphinx模块,转而使用coreseek包中提供的sphinxapi.php

ls /usr/local/coreseek/api/*.php

sphinxapi.php
test2.php
test_coreseek.php
test.php

test*.php都是demo,可以作为参考

自己写个test.php

vim test.php

include './sphinxapi.php';

$sphinx->SetServer ( '192.168.1.168', 9512 );
$sphinx->SetArrayResult ( true );

$index = 'message1';

$result = $sphinx->Query ( '搜索关键字', "*" );

if (!$result){
    print_r($sphinx->getLastError());
}

print_r($result);

其他的和sphinx一样


结束!