1.什么是Sphinx
Sphinx是俄罗斯人Andrew Aksyonoff开发的高性能全文搜索软件包,在GPL与商业协议双许可协议下发行。
全文检索式指以文档的全部文本信息作为检索对象的一种信息检索技术。检索的对象有可能是文章的标题,也有可能是文章的作者,也有可能是文章的摘要或内容。常用于新闻,论坛评论等的模糊查询。
2.Sphinx的特性
- 高速索引(在新款CPU上,近10MB/S);
- 高速搜索(2-4G的文本量平均查询速度不到0.1秒);
- 高可用性(单CPU上最大可支持100GB的文本,100M文档);
- 提供良好的相关性排名;
- 提供文档摘要生成;
- 提供从Mysql内部的插件式存储引擎上搜索;
- 支持布尔,短语,和近义词查询;
- 支持单字节编码与UTF-8编码等等。
3.下载coreseek
PS:Coreseek是基于Sphinx开发的,Sphinx只支持mysql,Coreseek支持更多,另外支持中文分词。
http://www.coreseek.cn/opensource/mmseg/
4.安装操作系统基础开发库以及mysql依赖库以支持mysql数据源和xml数据源
yum install make gcc g++ gcc-c++ libtool autoconf automake imake mysql-devel libxml2-devel expat-devel
(PS:小编使用的linux系统centos5.6测试的,操系作系统版本不同,需安装不同的库,具体请点击)
5.安装(编译安装)
5.1 解压
tar -zxvf coreseek-3.2.14.tar.gz
cd coreseek-3.2.14
5.2 安装mmseg
cd mmseg-3.2.14
./bootstrap #输出的warning信息可以忽略,但是出现error则需要解决
./configure --prefix=/usr/local/mmseg
make && make install
cd ..
5.3 安装coreseek
cd csft-3.2.14
sh buildconf.sh #输出的warning信息可以忽略,但是出现error则需要解决
./configure --prefix=/usr/local/coreseek --without-unixodbc --with-mmseg --with-mmseg-includes=/usr/local/mmseg/include/mmseg/ --with-mmseg-libs=/usr/local/mmseg/lib/ --with-mysql
make && make install
6.配置测试
cp /usr/local/coreseek/etc/sphinx-min.conf.dist /etc/csft.conf
/usr/local/coreseek/bin/indexer -c /etc/csft.conf
显示如下
7.配置csft.conf
vim /etc/csft.conf
#配置源
source sphinx_t0 #数据库名_数据表名,每配置一个数据表,都需要写上一个配置源
{
type = mysql #数据库类型
sql_host = localhost
sql_user = root
sql_pass = 123123
sql_db = sphinx #指定数据库
sql_port = 3306 # optional, default is 3306
sql_sock = /tmp/mysql.sock #mysql接口
#从数据库之中读取数据的SQL语句设置
#在这里尽可能不使用where或groupby,
#将where与groupby的内容交给sphinx,由sphinx进行条件过滤与groupby效率会更高
#注意:select的字段必须包括一个唯一主键以及要全文检索的字段(可以有多个)、输出的字段。
#where中要用到的字段也要select出来
#例:
#在配置sql语句,可以先写出一句预计要执行的sql语句,然后根据sphinx规定设置
#select * from t0 where description like '%广州%' or name like '%s%'
#=> select id,description,name,age from t0
sql_query = \
SELECT id, name, age, description,group_id,date_added \
FROM t0
sql_attr_uint = age
#使用sql_attr设置的字段(搜索条件),只能作为属性,使用SphinxClient::SetFilter()进行过滤;
#未被设置的字段,自动作为全文检索的字段,使用SphinxClient::Query("搜索字符串")进行全文搜索
#sql_query第一列id需为整数,且被系统使用,无需再设置sql_attr_uint
sql_attr_uint = group_id
sql_attr_timestamp = date_added #定义不同类型的字段要用不同的属性名,比如上面的sql_attr_timestamp就是时间戳类型
#sql_query_info = SELECT * FROM documents WHERE id=$id #命令行查询时,从数据库读取原始数据信息
#在执行sql_query前执行的sql命令, 可以有多条
sql_query_pre = SET NAMES utf8 #执行sql字符编码
}
#索引,每一源需要一个索引
index sphinx_t0 #索引名字一般与配置源一致
{
source = sphinx_t0 #source 关联源
path = /usr/local/coreseek/var/data/sphinx_t0 #索引文件存放路径,每个索引文件一个
docinfo = extern
charset_dictpath = /usr/local/mmseg/etc/ #指明分词法读取词典文件的位置,当启用分词法时,为必填项。在使用LibMMSeg作为分词 库时,需要确保词典文件uni.lib在指定的目录下
charset_type = zh_cn.utf-8 #字符编码
}
#索引,控制所有索引
indexer
{
mem_limit = 512M #内存
}
#sphinx守护进程配置
searchd
{
port = 9312 #端口
log = /usr/local/coreseek/var/log/searchd.log
query_log = /usr/local/coreseek/var/log/query.log
read_timeout = 5 #超时
max_children = 30 #最大连接数
pid_file = /usr/local/csft/var/log/searchd.pid #pid文件路径
max_matches = 1000 #max_matches最大匹配数,也就是查找的数据再多也只返回这里设置的1000条
seamless_rotate = 1
preopen_indexes = 0
unlink_old = 1
}
生成索引 /usr/local/coreseek/bin/indexer -c /etc/csft.conf sphinx_t0
启动 /usr/local/coreseek/bin/searchd -c /etc/csft.conf
至此,Sphinx基本安装完毕,接下来就是配合PHP使用
8.配合PHP使用
<?php
header('Content-Type:text/html;charset=utf-8'); //编码为utf-8
include 'sphinxapi.php'; // 加载Sphinx API,网上下载
$list= array();
if(!empty($_POST)){
$sc = new SphinxClient(); // 实例化Api
$sc->setServer('192.168.1.108', 9312); // 设置服务端,第一个参数sphinx服务器地址,第二个sphinx监听端口
$res = $sc->query($_POST['key'], 'sphinx_t0'); // 执行查询,第一个参数查询的关键字,第二个查询的索引名称,mysql索引名称(这个也是在配置文件中定义的),多个索引名称以,分开,也可以用*表示所有索引。
// print_r($sc);
print_r($res);exit;
}
?>
<form action="" method="post">
<input type="text" name="key" />
<input type="submit" value="提交" />
</form>
?>
注意:如果输出的结果是空白,可打印print_r($sc),查看错误代码。
错误代码10060:服务器防火墙没有开放9312端口,直接关闭防火墙即可 service iptables stop.
错误代码10061:可能是索引没有生成成功,构造好词典,重新生成索引或者searchd服务没有开启。
9.更新词典及词典的构造
9.1 从搜狗输入法官网下载所需要的词库
9.2 用深蓝词库转换器将下载好的词库转换成txt文件,深蓝词库google下载地址 深蓝词库github下载地址
9.3 用PHP代码将文件转换成符合词典规则的txt文件(注意:新生成的文件内容words_new.txt与原文件unigram.txt内容没有交集,因此可将新文件内容追加到unigram.txt,执行命令 cat /usr/local/mmseg/etc/words_new.txt >> /usr/local/mmseg/etc/unigram.txt)
<?php
ini_set('display_errors', 'On');
error_reporting(E_ALL);
date_default_timezone_set ('Asia/Shanghai');
set_time_limit(0);
$buffer = ini_get('output_buffering');
if($buffer){
ob_end_flush();
}
//注意文件的编码格式是utf8
echo '处理新词库...'.PHP_EOL; //PHP_EOL windwos相当于'\r\n',unix\linux相当于'\n'
flush();
$filename = "words.txt";
$handle = fopen ($filename, "r");
$content = fread ($handle, filesize ($filename));
fclose ($handle);
$content = trim($content);
$arr1 = explode( "\r\n" ,$content );
// print_r($arr1);exit;
$arr1 = array_flip(array_flip($arr1)); //反转数组的键值,剔除重复的值
foreach($arr1 as $key=>$value){
$value = dealchinese($value);
if(!empty($value)){
$arr1[$key] = $value;
}else{
unset($arr1[$key]);
}
}
// print_r($arr1);exit;
echo '处理原来词库...'.PHP_EOL;
flush();
$filename2 = "unigram.txt";
$handle2 = fopen ($filename2, "r");
$content2 = fread ($handle2, filesize ($filename2));
fclose ($handle2);
$content2 = dealchinese($content2,"\r\n");
$arr2 = explode( "\r\n" ,$content2 );
echo '删除相同词条...'.PHP_EOL;
flush();
$array_diff = array_diff($arr1,$arr2);
echo '格式化词库...'.PHP_EOL;
flush();
$words='';
foreach($array_diff as $k => $word){
$words .= $word."\t1".PHP_EOL."x:1".PHP_EOL;
}
//echo $words;
file_put_contents('words_new.txt',$words,FILE_APPEND); //写入文件
echo 'done!';
function dealChinese($str, $join=''){
preg_match_all('/[\x{4e00}-\x{9fff}]+/u', $str, $matches); //将中文字符全部匹配出来
$str = join($join, $matches[0]); //从匹配结果中重新组合
return $str;
}
?>
9.4 刷新中文分词
cd /usr/local/mmseg/bin
./mmseg -u ../etc/unigram.txt 产生一个名为unigram.txt.uni的文件
cd ..
cd etc
mv unigram.txt.uni uni.lib 将该文件名改为uni.lib,完成词典的构造
10.重新生成索引、重启服务
/usr/local/coreseek/bin/searchd -c /etc/csft.conf --stop #停止searchd服务
/usr/local/coreseek/bin/indexer -c /etc/csft.conf --all -rotate #重生所有索引
/usr/local/coreseek/bin/searchd -c /etc/csft.conf #启动searchd服务
注意:生成索引的过程中如果出现segmentation fault错误,可从以下三方面排查
情况一、uni.lib文件路径错误或找不到该文件
情况二、unigram.txt文件过大,一般不超过20W条数据
情况三、使用记事本等编辑器编辑过unigram.txt文件,造成词典文件格式不正确(最好使用notepad++打开)
情况四、unigram.txt文件内容排版不统一,文件尾部换行太多(经测试,最多只能空一行)。
至此,OVER