Sphinx + Coreseek 实现中文分词搜索

时间:2022-02-04 00:48:47

Sphinx + Coreseek 实现中文分词搜索

1. 全文检索

1.1 全文检索 vs. 数据库

全文检索是数据库的有力补充,全文检索并不能替代数据库在应用系统中的作用。当应用系统的数据以大量的文本信息为主时,采用全文检索技术可以极大的提升应用系统的价值。

  • 数据库搜索,如果搜索范围包括全部正文数据,往往性能很低,用户响应时间长(分钟级,经常超时);而全文检索可以在0.x秒(毫秒级)的时间内将结果反馈给用户;

  • 数据库搜索,一个用户在搜索,往往影响其他用户的对应用系统进行操作;全文检索可以同时支持多个用户并发搜索,其他对应用系统进行操作的用户不受影响;

  • 数据库搜索很难实现多个关键字的复合搜索;而全文检索可以实现多个关键词的复合搜索,包括 “和(AND)”、“或(OR)”、“否(NOT)” 等;

  • 数据库搜索难于对结果进行相关度排序,当检索结果多时,用户往往难于找到最恰当的文档;而全文检索通过统计的研究成果,可以将文档进行相关度排序后,再返回给用户,提高用户的效率;

  • 全文检索还可以对检索结果的数据进行聚类分析(Group, 这里的聚类和NLP里面的聚类算法不同),增进用户对数据分布情况的了解;

  • 全文检索需要用户定期执行建立索引的动作,比直接使用数据库搜索增加了维护的工作;

  • 实现的不完善的全文索引系统容易造成索引与数据库的不一致,反而降低了用户的使用体验;

  • 优秀的全文检索系统支持按照文档的不同字段分配不同的检索权重,根据应用的不同动态的改变结果的排序;

  • 对于中文、日文和韩文而言,全文检索支持分词,进一步缩小了结果集的范围;而数据库检索往往不支持,往往一些与搜索词毫不相干的内容也混入了结果集。

全文检索与数据库检索各有优势,需要根据具体应用场景的不同灵活选择。

1.2 中文检索 vs. 汉化检索

全文检索一般支持中文分词,而往往有人认为将现有的不支持中文分词的全文检索软件加入中文分词模块就可以使用了。这个观点本身没错,但是可以使用不代表可以用好。国内有大量的网站采用Lucene+中文分词的解决方案,但是搜索结果并不乐观。

中文全文检索绝不是简单的将国外的全文检索软件包加入中文分词模块(汉化的全文检索)。相比汉化的全文检索,中文全文检索引擎主要有如下优势:

  • 高精度的分词算法,有统计认为,中文分词的切分精度至少要达到>96% ,才能对全文检索的精度和准确率没有太大影响;

  • 为中文优化过的结果集排序算法,中文用户有使用长短语(短句)进行搜索的习惯,而汉化的全文搜索不考虑词与词之间的位置关系,严重影响了用户的使用体验;

  • 可以利用中文的词性信息,对于不同词性的词,给与不同的排序权重,进一步改善结果集。

1.3 自建全文搜索与使用Google等第三方网站提供的站内全文搜索的区别

对网站设备有要求
自建全文搜索往往需要站长有至少一*立主机,而使用第三方提供的全文搜索对站点的要求低,虚拟主机即可;不过,出现全文搜索需求的站点通常已经有自己的独立主机了。

索引更新更及时
由于搜索服务在第三方托管,其往往只能按照一定的规则定期更新索引库(往往是几小时、甚至几天才更新一次索引),您网站上的新出现的内容往往不能及时被搜索到;
使用自建全文搜索,可以保证您网站上新出现的内容可以”立即“被检索到。

更适应您的网站
由于中文需要进行分词的特性,导致没有一套通用的词库可以适用于全部网站,要得到优秀的检索结果需要定制一套适用于您网站的词库;
采用第三方的搜索服务,您是无法修改第三方厂商的词库的,而使用自建全文搜索则无此问题。

更有利于您网站的数据整合
有些网站不止是论坛,往往还包括内容管理(CMS)、商城等多种应用,而使用数据库搜索往往需要用户在各个系统中都进行搜索才能找到内容;
第三方的检索无法区别各个系统的不同。而自建的全文搜索可以有效的区分各个数据来源的不同数据,真正做到一次搜索应有尽有,从而改善您网站的访问体验,增加您网站的点击率。

避免您的访问者遇到某些尴尬
第三方的搜索结果页面不是您可以控制修改的,有推荐一些可能会使您网站访问者尴尬的搜索短语的可能。而使用自建全文搜索则完全无此问题。

2. Sphinx

Sphinx是一款基于SQL的高性能全文检索引擎,Sphinx的性能在众多全文检索引擎中也是数一数二的,利用Sphinx,我们可以完成比数据库本身更专业的搜索功能,而且可以有很多针对性的性能优化。

Sphinx的特点:

  • 快速创建索引:3分钟左右即可创建近100万条记录的索引,并且采用了增量索引的方式,重建索引非常迅速。

  • 闪电般的检索速度:尽管是1千万条的大数据量,查询数据的速度也在毫秒级以上,2-4G的文本量中平均查询速度不到0.1秒。

  • 为很多脚本语言设计了检索API,如PHP,Python,Perl,Ruby等,因此你可以在大部分编程应用中很方便地调用Sphinx的相关接口。

  • 为MySQL设计了一个存储引擎插件,因此如果你在MySQL上使用Sphinx,那简直就方便到家了。

  • 支持分布式搜索,可以横向扩展系统性能。

2. Coreseek介绍###

Sphinx 全文搜索引擎对英文等拉丁语系支持较好, 对中文等支持较差.

Coreseek 是一款中文全文检索/搜索软件,以GPLv2许可协议开源发布,基于Sphinx研发并独立发布,专攻中文搜索和信息处理领域,适用于行业/垂直搜索、论坛/站内搜索、数据库搜索、文档/文献检索、信息检索、数据挖掘等应用场景,用户可以免费下载使用. 并且在全面的中文手册, 方便部署和使用.

3. Coreseek安装使用

本章节概述Coreseek安装说明, 具体环境及详细说明请见Coreseek官方中文手册:http://www.coreseek.cn/products-install/step_by_step/

以下使用MySQL数据源进行说明.

第一步:安装
安装coreseek请参考:BSD、Linux、Windows系统安装测试说明文档;

安装后,请确保安装测试说明文档中的各项测试都可以通过,以便coreseek做好准备,为你服务!

第二步: 配置
在BSD/Linux安装包的testpack/etc目录下,放置了演示的配置文件;

  在Windows安装包的etc目录下,也放置了演示的配置文件;

  如果是mysql数据库,可以将csft_mysql.conf拷贝为自己的配置文件,然后进行修改!其他数据库可以参考python数据源;

  要查看配置的细节,可以访问Coreseek/Sphinx(0.9)中文手册了解详情和具体的配置参数。

  配置文件的核心,为source和index配置,两者是成对出现的;如果需要设置针对多种情况或者多个数据表的索引,则可针对每一个编写对应的source和index配置;

  source表示从何处取得原始数据,也就是数据源;index表示取得数据后如何索引;

  source配置中,请确保可以使用给出的数据库服务器地址、用户、密码连接到对应的数据库,执行获取数据的SQL语句可以得到数据;否则coreseek无法得到数据,也就无法提供服务了。

  一般情况下,sql_query给出读取数据的SQL语句,第一列为自增的ID字段,然后可以包括字符串字段,整数数值字段;整数数值字段需要在后面使用sql_attr_uint明确标注,有多个则分别标注即可。

  index配置中,需要注意修改path参数,确保不与其他的搜索服务发生冲突;最后的search的配置中,也要修改对应的路径参数和端口参数,以防止冲突发生;

第三步:测试

首先,索引:使用bin目录下的indexer,执行:indexer -c 配置文件的路径 index名称.

# /usr/local/coreseek/bin/indexer -c etc/csft.conf --all ##--all表示全部索引
##Windows下面为bin\indexer -c etc\csft.conf --all
##以下为正常索引全部数据时的提示信息:部分数据信息根据实际数据情况变化
Coreseek Fulltext 3.2 [ Sphinx 0.9.9-release (r2117)]
Copyright (c) 2007-2010,
Beijing Choice Software Technologies Inc (http://www.coreseek.com)

using config file 'etc/csft.conf'...
indexing index '索引名称'...
collected 3 docs, 0.0 MB
sorted 0.0 Mhits, 100.0% done
total 3 docs, 7585 bytes
total 0.075 sec, 101043 bytes/sec, 39.96 docs/sec
total 2 reads, 0.000 sec, 5.6 kb/call avg, 0.0 msec/call avg
total 7 writes, 0.000 sec, 3.9 kb/call avg, 0.0 msec/call avg

果出现以上对应的提示,则表示配置正确,可以正常索引

随后,启动搜索:使用bin目录下的searchd,执行:searchd -c 配置文件的路径 –console

# /usr/local/coreseek/bin/searchd -c etc/csft.conf --console
##Windows下面为bin\searchd -c etc\csft.conf --console
##以下为正常开启搜索服务时的提示信息:其中的port可以在配置文件中修改
Coreseek Fulltext 3.2 [ Sphinx 0.9.9-release (r2117)]
Copyright (c) 2007-2010,
Beijing Choice Software Technologies Inc (http://www.coreseek.com)

using config file 'etc/csft.conf'...
listening on all interfaces, port=9312

  如要继续测试搜索功能,请不要停止searchd,否则其他程序将无法连接到搜索服务端

  BSD/Linux环境下,测试成功后:

    如要后台运行服务,则使用:searchd -c 配置文件的路径,将searchd作为后台服务运行;

    如果要停止后台服务,则使用:searchd -c 配置文件的路径 –stop;

    如果要更新后台服务的索引,则使用:indexer -c 配置文件的路径 index名称

  如果要将搜索结果应用到自己的程序之中,请使用api目录下对应的api接口测试。PHP接口的测试如下:

//注意文件的编码格式需要保存为为UTF-8格式
require ( "sphinxapi.php" );

$cl = new SphinxClient ();
$cl->SetServer ( '127.0.0.1', 9312);
//以下设置用于返回数组形式的结果
$cl->SetArrayResult ( true );

/*
//ID的过滤
$cl->SetIDRange(3,4);

//sql_attr_uint等类型的属性字段,需要使用setFilter过滤,类似SQL的WHERE group_id=2
$cl->setFilter('group_id',array(2));

//sql_attr_uint等类型的属性字段,也可以设置过滤范围,类似SQL的WHERE group_id2>=6 AND group_id2<=8
$cl->SetFilterRange('group_id2',6,8);
*/

//取从头开始的前20条数据,0,20类似SQl语句的LIMIT 0,20
$cl->SetLimits(0,20);

//在做索引时,没有进行 sql_attr_类型 设置的字段,可以作为“搜索字符串”,进行全文搜索
$res = $cl->Query ( '搜索字符串', "*" ); //"*"表示在所有索引里面同时搜索,"索引名称(例如test或者test,test2)"则表示搜索指定的

//如果需要搜索指定全文字段的内容,可以使用扩展匹配模式:
//$cl->SetMatchMode(SPH_MATCH_EXTENDED);
//$res=cl->Query( '@title (测试)' , "*");
//$res=cl->Query( '@title (测试) @content ('网络')' , "*");

echo '<pre>';
print_r($res['matches']);
print_r($res);
print_r($cl->GetLastError());
print_r($cl->GetLastWarning());
echo '</pre>';

搜索结果示例:

Array
(
[error] => 【本次查询的错误信息】
[warning] =>
[status] => 0
[fields] => Array
(
[0] => title
[1] => content
)

[attrs] => Array
(
[published] => 2
[author_id] => 1
[a] => 1
)

[matches] => Array 【匹配到的文档信息】
(
[0] => Array
(
[id] => 3 【文档的ID】
[weight] => 1680
[attrs] => Array
(
[published] => 1270094460
[author_id] => 2
[a] => 0
)

)

)

[total] => 1 【本次查询返回的结果数目,例如翻页等使用】
[total_found] => 1 【整个系统包含的结果数目】
[time] => 0.136 【查询使用的时间】
[words] => Array 【分词结果】
(
[服务器] => Array
(
[docs] => 1 【该词汇匹配到的文档数目】
[hits] => 1 【该词汇出现的次数】
)

)

)