Sphinx + Coreseek 实现中文分词搜索

时间:2023-08-27 23:58:32

Sphinx + Coreseek 实现中文分词搜索

1. 全文检索

1.1 全文检索 vs. 数据库

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

  • 数据库搜索。假设搜索范围包含所有正文数据。往往性能非常低。用户响应时间长(分钟级。常常超时);而全文检索能够在0.x秒(毫秒级)的时间内将结果反馈给用户;

  • 数据库搜索。一个用户在搜索。往往影响其它用户的相应用系统进行操作。全文检索能够同一时候支持多个用户并发搜索,其它相应用系统进行操作的用户不受影响。

  • 数据库搜索非常难实现多个关键字的复合搜索。而全文检索能够实现多个关键词的复合搜索。包含 “和(AND)”、“或(OR)”、“否(NOT)” 等;

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

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

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

  • 实现的不完好的全文索引系统easy造成索引与数据库的不一致,反而减少了用户的使用体验;

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

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

全文检索与数据库检索各有优势,须要依据详细应用场景的不同灵活选择。

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配置中,请确保能够使用给出的数据库server地址、用户、password连接到相应的数据库,运行获取数据的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 【分词结果】
(
[server] => Array
(
[docs] => 1 【该词汇匹配到的文档数目】
[hits] => 1 【该词汇出现的次数】
) ) )