学习使用全文检索工具后,做一个小结。
其实这个工具用起来非常简单,只需要花几个小时专心阅读完开发手册就可以进入开发阶段了。
讯搜全文检索工具(Xunsearch)
首先它是一款开源的工具,和其它的开源工具一样,简单易用而且功能强大,并且性能也非常卓越。
分词与索引,是全文检索工具的关键。
讯搜底层采用 C/C++ 编写,索引设计基于著名而悠久的 Xapian,分词采用 自主研发同样也是开源的 SCWS分词,两者完美结合,理论上单个搜索库支持 40 亿条 记录。可编译运行于 Linux/FreeBSD 等各种 UNIX 类型的系统。
讯搜优势之处:
- 开源免费 Xunsearch 全面开源,并使用最流行的开源许可协议 GPL 发布。任何人均可以免费 获取本项目的全部源代码,并在许可条件下修改和再分发。
- 分布式架构搜索程序的前端和后端可以分离部署在不同服务器中,对于大规模的搜索应用还可以 对索引进行水平、垂直切割。
- 开发难度极低一般开发者只要在安装和设置完成后,通过提供的脚本 SDK 包,便可十分容易的进行 二次开发,打造出自己的全文搜索引擎。
- 功能强大支持字段检索、结果高亮、字段排序、布尔语法、区间检索、聚合搜索、相关搜索、 权重微调、拼音搜索、搜索建议等专业搜索引擎具备的各项功能。这也是本项目 相对于其它开源搜索软件的重要优势。
简单来说,就是安装使用简单,分布式支持中文分词。
安装讯搜服务器
运行下面指令下载、解压安装包
wget http://www.xunsearch.com/download/xunsearch-full-latest.tar.bz2 tar -xjf xunsearch-full-latest.tar.bz2
执行安装脚本,根据提示进行操作,主要是输入 xunsearch 软件包的安装目录,强烈建议单独 规划一个目录,而不是混到别的软件目录中。
cd xunsearch-full-1.3.0/ sh setup.sh
第一次安装的话,过程可能会稍显漫长,请不必着急,您大可泡杯茶一边喝一边等待即可。
待命令运行结束后,如果没有出错中断,则表示顺利安装完成,然后就可以启动/重新启动 xunsearch 的后台服务,下面命令中的 $prefix 请务必替换为您的安装目录,而不是照抄。
cd $prefix ; bin/xs-ctl.sh restart
强烈建议您将此命令添加到开机启动脚本中,以便每次服务器重启后能自动启动搜索服务程序, 在 Linux 系统中您可以将脚本指令写进 /etc/rc.local 即可。
有必要指出的是,关于搜索项目的数据目录规划。搜索系统将所有数据保存在 $prefix/data 目录中。 如果您希望数据目录另行安排或转移至其它分区,请将 $prefix/data 作为软链接指向真实目录。
bin下为启动目录,data索引保存位置,默认安装完成后附带有sdk。
sdk目录结构
_
|- doc/ 离线 HTML 版相关文档
|- app/ 用于存放搜索项目的 ini 文件
|- lib/XS.php 入口文件,所有搜索功能必须且只需包含此文件
|- util/ 辅助工具程序目录
|- RequireCheck.php 用于检测您的 PHP 环境是否符合运行条件
|- IniWizzaard.php 用于帮助您编写 xunsearch 项目配置文件
|- Quest.php 搜索测试工具
|- Indexer.php 索引管理工具
如果您的搜索应用程序和 xunsearch 在同一台服务器,则无需复制任何代码,在开发的时候直接包含 入口文件$prefix/sdk/php/lib/XS.php 即可。代码如下:
require_once ‘$prefix/sdk/php/lib/XS.php‘;
编写项目配置文件
示例:index.ini
1 project.name = sample 2 project.default_charset = GBK 3 ;server.index = 8383 4 ;server.search = 8384 5 6 [pid] 7 type = id 8 9 [subject] 10 type = title 11 12 [message] 13 type = body 14 15 [dateline] 16 type = numeric 17 18 [author] 19 index = both 20 21 [authorid] 22 23 [tid] 24 index = self 25 tokenizer = full 26 27 [fid] 28 index = self 29 tokenizer = full 30 31 [flag]
规则含义解析:
定义字段
每个字段用一个区段配置来表示,中括号内的名字即为字段名。每个项目包含若干个字段, 具体由项目搜索需求决定,并不需要一味的与实际源数据库 (如 MYSQL) 一致, 而只需要设计搜索功能所涉及的字段即可。
[field_name]
字段选项
每个字段根据实际情况指定字段选项,所有选项均有默认值,所以即便不指定任何选项而只有中括号定义的字段, 那也是一个合法的字段,字段选项包括以下几种:
type 字段类型
- string 字符型,适用多数情况,也是默认值
- numeric 数值型,包含整型和浮点数,仅当字段需用于以排序或区间检索时才设为该类型,否则请使用 string 即可
- date 日期型,形式为 YYYYmmdd 这样固定的 8 字节,如果没有区间检索或排序需求不建议使用
- id 主键型,确保每条数据具备唯一值,是索引更新和删除的凭据,每个搜索项目必须有且仅有一个 id 字段,该字段的值不区分大小写
- title 标题型,标题或名称字段,至多有一个该类型的字段
- body 内容型,主内容字段, 即本搜索项目中内容最长的字段,至多只有一个该类型字段,本字段不支持字段检索
type = string
index 索引方式
xunsearch 的索引有 2 种模式:其一是不标明字段的检索,称之为“混合区检索”;其二是标明特定字段的“字段检索”。 例如:搜索 XXX YYY 表示在混合区检索,返回的结果可能是 title 也有可能是 body 字段符合匹配; 而搜索 title:XXX 则表示仅检索 title 匹配 XXX 的数据。每个字段可以指定的索引方式的值如下:
- none 不做索引,所有的搜索匹配均与本字段无关,这个字段只用于排序或搜索结果展示用到。
- self 字段索引,可以在搜索时用 field:XXX 来检索本字段
- mixed 混合区索引,不标明字段的默认搜索也可以检索本字段
- both 相当于 self + mixed,两种情况均索引
通常情况默认值为 none ,但 id 型字段默认是 self ,title 型字段是 both ,body 型字段则固定为 mixed 。
index = none
tokenizer 分词器
默认为 default 采用内置的功能强大的 scws 分词,适合绝大多数字符串字段。也可以指定自定义分词器, 格式为 name 或 name(arg) 两种形式,其中 name 是分词器名称,arg 则是传递给分词器构造函数的参数。 自定义分词器需要在 lib/ 目录下编写名为 XSTokenizerName 的分词类并实现接口 XSTokenizer, 内置支持的分词器有以下几种:
- full 表示本字段的值整体作为一个检索词,像各种 ID 都适合这种情况
- none 表示本字段没有任何词汇用于索引
- split([ ]) 表示根据参数分割内容,默认参数为空格,若参数以 / 开头并以 / 结尾则 内部调用preg_split(arg, ..) 来分割取词,以支持正则或其它特殊字符分割
- xlen([2]) 表示根据指定参数长度分段取词,如 ABCDEF => AB + CD + EF
- xstep([2]) 表示根据指定参数步长逐段取词,如 ABCDEF => AB + ABCD + ABCDEF
- scws([3]) 表示采用指定参数为复合等级的 scws 分词,(若无特殊复合需求,无需指定)
tokenizer = default
cutlen 搜索结果摘要截取长度
默认值为 0 表示不截取。主要是针对某些内容特别长的字段在返回结果时自动剪取包含关键词的一小段文字。 典型的是 body 型字段默认为 300 。长度单位是字节,通常 UTF-8 编码的一个汉字为 3 个字节。
cutlen = 0
weight 混合区检索时的概率权重
在混合检索时,可以对标题和内容等不同字段进行权重计算,如果你不想该字段参与计算权重可设为 0 。 通常默认值为 1 ,但 title 型默认为 5 而 body 型则固定为 1 。
weight = 1
phrase 是否支持精确检索
即当给搜索语句加上引号时,则要求匹配的结果必须严格按照搜索词的顺序匹配,此外还支持用 NEAR 之类的语法来做精确检索,具体参见:搜索技巧 。通常默认值为 no 但是 title 和 body 型字段默认则为 yes 。值得注意的是该功能仅支持默认分词器,如非必要请勿开启此项, 因为这会增加索引数据的大小。
phrase = no
non_bool 强制指定是否为布尔索引
布尔索引不参与权重排名计算,默认情况下所有自定义分词器的字段均为布尔索引。因此, 当您使用自定义分词器却又想让本字段参与权重计算的话,请将本项设为 yes。
non_bool = yes
注意,如果索引服务器与应用服务器不是同一台时:
Info: 出于性能和多数需求考虑 xunsearch 服务端和 SDK API 通讯时没有加密和验证处理, 并且默认情况 xs-ctl.sh 启动的服务程序是绑定并监听在 127.0.0.1 上。
如果您的 SDK 调用和 xunsearch 服务端不在同一服务器,请使用 -b inet 方式启动脚本, 并注意借助类似 iptables 的防火墙来控制 xunsearch 的 8383/8384 两个端口的访问权限。 启动脚本用法举例如下,以下均为合法使用方式:
bin/xs-ctl.sh -b local start // 监听在本地回环地址 127.0.0.1 上
bin/xs-ctl.sh -b inet start // 监听在所有本地 IP 地址上
bin/xs-ctl.sh -b a.b.c.d start // 监听在指定 IP 上
bin/xs-ctl.sh -b unix start // 分别监听在 tmp/indexd.sock 和 tmp/search
创建索引
1 require(BASE_DATA_PATH.‘/api/xs/lib/XS.php‘); 2 $this->_doc = new XSDocument(); 3 $this->_xs = new XS(‘index‘); //项目配置文件名称 4 $this->_index = $this->_xs->index; 5 $this->_search = $this->_xs->search; 6 $this->_search->setCharset(CHARSET); 7 //建立文档 8 $index_data[‘pk‘] = $v[‘goods_id‘]; 9 $index_data[‘goods_id‘] = $v[‘goods_id‘]; 10 $index_data[‘goods_name‘] = $v[‘goods_name‘]; 11 //更新文档到索引 12 $this->_doc->setFields($index_data); 13 $this->_index->update($this->_doc);
使用查询
1 require(BASE_DATA_PATH.‘/api/xs/lib/XS.php‘); 2 $this->_xs = new XS(‘index‘); 3 $this->_index = $this->_xs->index; 4 $this->_search = $this->_xs->search; 5 6 $query = $keywords; // 这里的搜索语句很简单,就一个短语 7 $this->_search->setFuzzy(); 8 $this->_search->setQuery($query); // 设置搜索语句 9 //$this->_search->addWeight(‘subject‘, ‘xunsearch‘); // 增加附加条件:提升标题中包含 ‘xunsearch‘ 的记录的权重 10 $this->_search->setLimit(5,10); // 设置返回结果最多为 5 条,并跳过前 10 条 11 12 $docs = $this->_search->search(); // 执行搜索,将搜索结果文档保存在 $docs 数组中 13 $count = $this->_search->count(); // 获取搜索结果的匹配总数估算值 14 //var_dump($docs); 15
end