一、安装
sphinx在此处下载: http://sphinxsearch.com/downloads/release/ 本次我下的是2.2.4版本 自持中文分词的包叫做coreseek,其实就是带了中文分词插件的sphinx,在此处下载: http://www.coreseek.cn/稳定版3.2.14内带的的sphinx还是 0.9.9 release版本的;
下面先来讲sphinx的安装和配置:
http://sphinxsearch.com/files/sphinx-2.1.3-release.tar.gz(建议安装这个,把包下载下来)
http://sphinxsearch.com/fies/sphinx-2.2.6-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 } =======================================配置文件说明完毕==============================*/
二、创建索引
这样配置就完成了,接下来要生成索引和开启守护进程:
/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
如果重建索引时守护进程正在运行,会报错,需要运行下面的指令,会重建索引并且重开守护进程 /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
(1)全PHP加载Sphinx模块
wget http://pecl.php.net/get/sphinx-1.1.0.tgz
tar zxf sphinx-1.1.0.tgz
cd /www/soft/sphinx-1.1.0
/usr/local/webserver/php/bin/phpize
./configure --with-php-config=/usr/local/webserver/php/bin/php-config
提示出错:
checking for libsphinxclient headers in default path... not found
configure: error: Cannot find libsphinxclient headers
找了下libsphinxclient,在/www/soft/csft-3.2.13/api/libsphinxclient,之前安装的是coreseek3.2.13版
cd libsphinxclient/
./configure
make && make install
安装完libsphinxclient,继续安装sphinx扩展
cd /www/soft/sphinx-1.1.0
/usr/local/php/bin/phpize
./configure --with-php-config=/usr/local/php/bin/php-config
make && make install
cd /usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/
看到sphinx.so
vi /usr/local/webserver/php/etc/php.ini
加入extension = sphinx.so
/usr/local/apache2/bin/apachectl restart
测试Sphinx模块,http://192.168.10.1/phpinfo.php
(2)、使用API类连接Sphinx程序
需要到coreseek解压包中找到sphinxapi.php文件,放到程序目录下
cp /lamp/coreseek-3.2.14/csft-3.2.14/api/sphinxapi.php /usr/local/apache2/htdocs/
include 'sphinxapi.php';
//加载Sphinx API
四、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);
sphinx调用模式:
大家都知道sphinx自带的一些匹配模式。主要有
setMatchMode:
SPH_MATCH_ALL匹配所有查询词(默认模式)
SPH_MATCH_ANY匹配查询词中的任意一个
SPH_MATCH_PHRASE将整个查询看作一个词组,要求按顺序完整匹配
SPH_MATCH_BOOLEAN将查询看作一个布尔表达式
SPH_MATCH_EXTENDED将查询看作一个Sphinx内部查询语言的表达式
SPH_MATCH_FULLSCAN使用完全扫描,忽略查询词汇
SPH_MATCH_EXTENDED2类似 SPH_MATCH_EXTENDED ,并支持评分和权重.
开通服务器9312端口:
lsof -i:9312这是查看某端口号开了没有 //注意:当重建索引时,需要重启searchd监听端口,否则返回 bool(false) 杀死进程: pkill -9 searchd 重启进程: ./searchd
五、安装中文版coreseek 现在来讲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=......搜索测试: /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';
//require_once "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一样 结束!
=============================
其他:
//sphinx搜索
//使用setLimits函数改变默认显示20条结果 $sphinx = new SphinxClient(); $sphinx->SetServer('localhost', 9312); $sphinx->SetMatchMode(SPH_MATCH_ANY); $sphinx->setLimits (0,1000); $result = $sphinx->query($word,'*');
//高亮显示的配置参数的数组 $opts = array( "before_match" => "<span class=/"highlight/">", "after_match" => "</span>", "chunk_separator" => "...", "limit" => 60,//摘要最多包含的符号(码点)数。整数,默认为 256 "around" => 25,//每个关键词块左右选取的词的数目。整数,默认为 5. "single_passage" => true,//是否仅抽取最佳的一个段落。 "exact_phrase" => false//是否仅高亮精确匹配的整个查询词组,而不是单独的关键词。布尔值,默认为假。 );
三、匹配模式
匹配模式:SetMatchMode(设置匹配模式)
原型:function SetMatchMode ( $mode )
SPH_MATCH_ALL 匹配所有查询词(默认模式).
SPH_MATCH_ANY 匹配查询词中的任意一个.
SPH_MATCH_PHRASE 将整个查询看作一个词组,要求按顺序完整匹配.
SPH_MATCH_BOOLEAN 将查询看作一个布尔表达式.
SPH_MATCH_EXTENDED 将查询看作一个 Sphinx 内部查询语言的表达式.
SPH_MATCH_FULLSCAN 使用完全扫描,忽略查询词汇.
SPH_MATCH_EXTENDED2 类似 SPH_MATCH_EXTENDED ,并支持评分和权重
调用代码:
PHP代码实例: Vi index.php <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> </head> <body> <h1>简单PHP搜索测试</h1> <form action="find.php" method=post> 请输入搜索关键字:<input type="text" name="word"><br> <input type="submit" name="submit"><br> </form> </body> </html> Vi find.php <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title>Find</title> </head> <body> <h1 id='top'>查询输出页面</h1> <?php $keyword=$_POST['word']; $sphinx=new SphinxClient(); $sphinx->SetServer("localhost",9312); $sphinx->SetMatchMode(SPH_MATCH_ANY); //$sphinx->setLimits(0,0);$result=$sphinx->query("$keyword","*"); //echo "<pre>"; //print_r($result); //echo "</pre>";$ids=join(",",array_keys($result['matches'])); mysql_connect("localhost","root","123"); mysql_select_db("test"); $sql="select * from post where id in({$ids})"; mysql_query("set names utf8"); $rst=mysql_query($sql); $opts=array( "before_match"=>"<button style='font-weight:bold;color:#f00'>", "after_match"=>"</button>" ); while($row=mysql_fetch_assoc($rst)){ $rst2=$sphinx->buildExcerpts($row,"main",$keyword,$opts); echo "第{$rst2[0]}篇贴子<br>"; echo "标题: {$rst2[1]}<br>"; echo "内容: {$rst2[2]}<br>"; echo "<hr>"; } ?> <body> <html>