sphinx中文分词搜索coreseek windows下安装与基本使用简介
首先说明一下coreseek其实就是基于sphinx的中文分词版本,sphinx本身并没有提供中文分词功能,需要自行安装中文词库比较麻烦,coreseek提供了中文分词功能,提供了完整的官方中文使用文档,并且在使用上和官方的sphinx并没有差别。以coreseek-4.1版本为例
下载地址 http://www.coreseek.cn/news/14/54/
帮助手册 http://www.coreseek.cn/products-install/#doc_cn
下面开始coreseek的安装
安装过程很简单,下载coreseek-4.1-win32.zip,解压至某一个文件夹,这里假设放在d:\coreseek下,双击打开test.cmd进行测试,会出来一串命令行的提示信息,留意提示信息,如果没有提示错误就算安装完成
安装后,先别急着怎么使用,首先要配置好文档,解缩包中有测试文件这里测试也略,教程尽量简单点(其实是我懒。。)
配置文件的位置可以放在任何地方,不过建议就放在d:\coreseek\bin\的目录好了,d:\coreseek\etc\目录下提供了好多配置的 参考,我们把csft_mysql.conf复制至d:\coreseek\bin\下,命名为sphinx.conf(可任意名称),打开它看到的内容 大概是这样:
#源定义
source mysql
{
type = mysql
sql_host = localhost
sql_user = root
sql_pass =
sql_db = test
sql_port = 3306
sql_query_pre = SET NAMES utf8
sql_query = SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, title, content FROM documents
#sql_query第一列id需为整数
#title、content作为字符串/文本字段,被全文索引
sql_attr_uint = group_id #从SQL读取到的值必须为整数
sql_attr_timestamp = date_added #从SQL读取到的值必须为整数,作为时间属性
sql_query_info_pre = SET NAMES utf8 #命令行查询时,设置正确的字符集
sql_query_info = SELECT * FROM documents WHERE id=$id #命令行查询时,从数据库读取原始数据信息
}
#index定义
index mysql
{
source = mysql #对应的source名称
path = var/data/mysql #请修改为实际使用的绝对路径,例如:/usr/local/coreseek/var/...
docinfo = extern
mlock = 0
morphology = none
min_word_len = 1
html_strip = 0
#中文分词配置,详情请查看:http://www.coreseek.cn/products-install/coreseek_mmseg/
#charset_dictpath = /usr/local/mmseg3/etc/ #BSD、Linux环境下设置,/符号结尾
charset_dictpath = etc/ #Windows环境下设置,/符号结尾,最好给出绝对路径,例如:C:/usr/local/coreseek/etc/...
charset_type = zh_cn.utf-8
}
#全局index定义
indexer
{
mem_limit = 128M
}
#searchd服务定义
searchd
{
listen = 9312
read_timeout = 5
max_children = 30
max_matches = 1000
seamless_rotate = 0
preopen_indexes = 0
unlink_old = 1
pid_file = var/log/searchd_mysql.pid #请修改为实际使用的绝对路径,例如:/usr/local/coreseek/var/...
log = var/log/searchd_mysql.log #请修改为实际使用的绝对路径,例如:/usr/local/coreseek/var/...
query_log = var/log/query_mysql.log #请修改为实际使用的绝对路径,例如:/usr/local/coreseek/var/...
binlog_path = #关闭binlog日志
}
这么多字段干嘛用的。。。
先别管这个,看文件中的配置格式
source mysql
{
...
}
index mysql
{
...
}
....
这些就是配置文件中的'类',配置格式就是以类为基础的,类的格式是 '关键字 [名称] {}',每个关键字的作用:
source:定义数据索引源(就是被搜索的数据啦),如果以mysql为索引源,那么source里的信息包含数据库账号、密码、端口、获取数据索引的sql语句等
index:定义如何处理索引源,例如索引文件目录、分词单位、分词配置文件、去除数据的html标签等
indexer:定义indexer服务设置,例如内存使用大小限制、文件索引大小限制
searchd:定义searchd服务设置,用于搜索时的设置,例如服务端口、搜索最大数量限制、搜索超时时间等
其实配置文件中好多字段都有默认值的,并不需要我们进行配置(不用写出来),下面对一些常用的配置字段进行解释,以mysql数据库为例
基本环境:
主机 localhost
账号 root
密码 root
端口 3306
数据库 ibos
数据表:email
数据结构:
CREATE TABLE email (
emailid mediumint(8) unsigned NOT NULL auto_increment COMMENT '邮件id',
fromid int(10) unsigned NOT NULL default '0' COMMENT '发送人ID',
toid int(10) unsigned NOT NULL default '0' COMMENT '收件人ID',content text unsigned NOT NULL COMMENT '邮件内容',
subject varchar(100) unsigned NOT NULL COMMENT '邮件标题',
sendtime int(10) NOT NULL COMMENT '发送时间',
attachment varchar(100) NOT NULL COMMENT '附件ID,以逗号分割',
PRIMARY KEY (emailid),
) ENGINE=MyISAM';
配置内容:
#定义数据源,取一个好听的名字,就叫email吧。。。
source attach {
type = mysql #定义数据源的类型
sql_host = localhost
sql_user = root
sql_pass = root
sql_db = ibos
sql_port = 3306
#sql_query_pre是获取数据源前执行的操作,内容是mysql可执行的语句,你可以设置多个sql_query_pre,sphinx将会按顺序执行
sql_query_pre = SET NAMES utf8 #一般设置好编码以保证数据格式正确
sql_query_pre = xxx
#sql_query就是真正获取数据源的语句,内容是mysql可执行的语句
#SELECT的第一个字段是非负整数并且值都不相同的,搜索结果返回的ID就是这个,建议使用数据表的主键,这里是emailid
#其它字段是用来设置搜索条件和希望被搜索的字段,如果那个字段你认为对搜索没有作用,那就不要选择
sql_query = SELECT emailid,fromid,toid,subject,content,sendtime,attachement FROM email
#sql_attr_ 索引属性,主要被用来设置搜索条件,并且搜索结果返回的信息也包含这些属性的值
#设置某个属性的前提是在sql_query中有返回这个字段的数据
#sql_attr_uint,从SQL读取到的值必须为整数
sql_attr_uint = fromid
sql_attr_uint = toid
#sql_attr_timestamp,从SQL读取到的值必须为整数,作为时间属性
sql_attr_timestamp = sendtime
#程序运行前执行的查询操作,这个没有什么意义,可以不写,仅仅用于调试目的
sql_query_info = SELECT * FROM email
}
#接下来要配置如何处理索引源,名称建议和索引源一样吧
index email {
source = email #对应的source名称
path = d:\coreseek\data\email #生成索引文件的路径(包含文件名),可自定义
min_word_len = 1 #最小分词长度
html_strip = 1 #是否去除html标签,强烈建议开启此项,像邮件这些富文本包含大量html标签,对搜索没有任何帮助,而且增加搜索时间和索引文件大小(至少增大5倍以上)
charset_dictpath = d:\coreseek\etc\ #中文分词配置文件目录
charset_type = zh_cn.utf-8
}
#还可以定义多个索引源
source diary {
}
index diary {
source :diary
}
#indexer服务定义,注意没有名字!这个设置是全局的!
indexer {
mem_limit = 128M #内存大小限制
}
#searchd服务定义,注意没有名字!这个设置是全局的!
searchd {
listen = 9312 #服务端口,默认9312
read_timeout = 5 #最大搜索时间
max_matches = 1000 #最大匹配数
max_children = 30 #子进程数目限制
#这几项看文档吧
pid_file = d:\coreseek\var\log\searchd_mysql.pid
log = d:\coreseek\var\log\searchd_mysql.log #全部searchd运行时事件会被记录在这个日志文件中。
query_log = d:\coreseek\var\log\query_mysql.log #全部搜索查询会被记录在此文件中
}
好了,配置就到这里,那如何进行搜索,那就要用到cmd命令行,别吓着了,其实我们记住三个命令就可以了
开始 - 运行 - cmd 打开命令行模式
建立索引
d:\coreseek\bin\indexer -c d:\coreseek\bin\sphinx.conf --all #sphinx.conf就是刚刚我们的配置文件
按回车,如无意外会看到正在建立索引的信息,稍等一会就可以了
开始搜索,注意命令行模式并不支持中文搜索(用其它方式,例如PHP没问题),coreseek官方有解决办法,但是我们一般不用命令行进行搜索,这里只是测试
d:\coreseek\bin\search -c d:\coreseek\bin\sphinx.conf 搜索字符串
例:搜索banana
d:\coreseek\bin\search -c d:\coreseek\bin\sphinx.conf banana
如无意外就会有搜索结果信息了。。。
打开控制台,这条和搜索那条命令不一样,是searchd不是search,这个命令下一篇讲PHP的时候会用到
d:\coreseek\bin\searchd -c d:\coreseek\bin\sphinx.conf #Ctrl + c 可关闭控制台
打开控制台的作用就是让让sphinx监听端口,接收搜索命令,例如用PHP代码执行sphinx搜索就要打开控制台
更多知识
继承
因为是类,所以可以继承。。
定义父类email
source email {
....
}
定义子类subemail继承email类的所有设置:
source subemail : email { #除了source,index也可以使用继承
....
}
子类中可以重载email中的设置
source subemail : email {
sql_host = www.ibos.com.cn #重载主机
sql_query = SELECT * FROM subemail #重载sql_query语句
}
其实继承很少被使用到,但有一个很实用的例子就是有很多数据源使用同一数据库的时候,继承就派上用场了
source setdb { #setdb类只实现连接数据库
sql_host = localhost
sql_user = root
sql_pass = root
sql_db = ibos
sql_port = 3306
}
souce email : setdb{ #继承setdb类
sql_query = ... #直接写查询语句,而不用再写数据库信息
}
souce diary : setdb {
sql_query = ...
}
souce article : setdb {
sql_query = ...
}
souce forum : setdb {
sql_query = ...
}
增量索引
以下是出自官方文档,觉得官方解释得比较清楚,更多例子参考文章中的附件 IBOS的配置文件中email的增量索引配置
有这么一种常见的情况:整个数据集非常大,以至于难于经常性的重建索引,但是每次新增的记录却相当地少。一个典型的例子是:一个论坛有1000000个已经归档的帖子,但每天只有1000个新帖子。
在这种情况下可以用所谓的“主索引+增量索引”(main+delta)模式来实现“近实时”的索引更新。
这种方法的基本思路是设置两个数据源和两个索引,对很少更新或根本不更新的数据建立主索引,而对新增文档建立增量索引。在上述例子中,那1000000个已经归档的帖子放在主索引中,而每天新增的1000个帖子则放在增量索引中。增量索引更新的频率可以非常快,而文档可以在出现几分 种内就可以被检索到。
确定具体某一文档的分属那个索引的分类工作可以自动完成。一个可选的方案是,建立一个计数表,记录将文档集分成两部分的那个文档ID,而每次重新构建主索引时,这个表都会被更新。
# in MySQL
CREATE TABLE sph_counter
(
counter_id INTEGER PRIMARY KEY NOT NULL,
max_doc_id INTEGER NOT NULL
);
# in sphinx.conf
source main
{
# ...
sql_query_pre = SET NAMES utf8
sql_query_pre = REPLACE INTO sph_counter SELECT 1, MAX(id) FROM documents
sql_query = SELECT id, title, body FROM documents \
WHERE id<=( SELECT max_doc_id FROM sph_counter WHERE counter_id=1 )
}
source delta : main
{
sql_query_pre = SET NAMES utf8
sql_query = SELECT id, title, body FROM documents \
WHERE id>( SELECT max_doc_id FROM sph_counter WHERE counter_id=1 )
}
index main
{
source = main
path = /path/to/main
# ... all the other settings
}
# note how all other settings are copied from main,
# but source and path are overridden (they MUST be)
index delta : main
{
source = delta
path = /path/to/delta
}
请注意,上例中我们显示设置了数据源delta的sql_query_pre选项,覆盖了全局设置。必须显示地覆盖这个选项,否则对delta做索引的时候也会运行那条REPLACE查询,那样会导致delta源中选出的数据为空。可是简单地将delta的sql_query_pre设置成空也不行,因为在继承来的数据源上第一次运行这个指令的时候,继承来的所有值都会被清空,这样编码设置的部分也会丢失。因此需要再次显式调用编码设置查询。
基础
以上一篇的email数据表为例:
数据结构:
CREATE TABLE email ( emailid mediumint(8) unsigned NOT NULL auto_increment COMMENT '邮件id', fromid int(10) unsigned NOT NULL default '0' COMMENT '发送人ID', toid int(10) unsigned NOT NULL default '0' COMMENT '收件人ID', content text unsigned NOT NULL COMMENT '邮件内容', subjectvarchar(100) unsigned NOT NULL COMMENT '邮件标题', sendtime int(10)NOT NULL COMMENT '发送时间', attachmentvarchar(100)NOT NULL COMMENT '附件ID,以逗号分割',PRIMARY KEY (emailid), ) ENGINE=MyISAM';
使用打开控制台,必需打开控制台PHP才能连接到sphinx(确保你已经建立好索引源):
d:\coreseek\bin\searchd -c d:\coreseek\bin\sphinx.conf
coreseek/api目录下提供了PHP的接口文件 sphinxapi.php,这个文件包含一个SphinxClient的类
在PHP引入这个文件,new一下
$sphinx = new SphinxClient();
//sphinx的主机名和端口
$sphinx->SetServer ( 'localhost', 9312 );
//设置返回结果集为php数组格式
$sphinx->SetArrayResult ( true );
//匹配结果的偏移量,参数的意义依次为:起始位置,返回结果条数,最大匹配条数
$sphinx->SetLimits(0, 20, 1000);
//最大搜索时间
$sphinx->SetMaxQueryTime(10);
//执行简单的搜索,这个搜索将会查询所有字段的信息,要查询指定的字段请继续看下文
$index = 'email' //索引源是配置文件中的 index 类,如果有多个索引源可使用,号隔开:'email,diary' 或者使用'*'号代表全部索引源
$result = $sphinx->query ('搜索关键字', $index);
echo '<pre>';
print_r($result);
echo '</pre>';
$result是一个数组,其中
total是匹配到的数据总数量
matches是匹配的数据,包含id,attrs这些信息
words是搜索关键字的分词
你可能奇怪为什么没有邮件的内容这些信息,其实sphinx并不会返回像mysql那样的数据数组,因为sphinx本来就没有记录完整的数据,只记录被分词后的数据。
具体还要看matches数组,matches中的ID就是指配置文件中sql_query SELECT语句中的第一个字段,我们配置文件中是这样的
sql_query = SELECT emailid,fromid,toid,subject,content,sendtime,attachement FROM email
所以matches中的ID是指emailid
至于weight是指匹配的权重,一般权重越高被返回的优先度也最高,匹配权重相关内容请参考官方文档
attrs是配置文件中sql_attr_ 中的信息,稍后会提到这些属性的用法
说了这么多,即使搜索到结果也不是我们想要的email数据,但事实sphinx是不记录真实数据的,所以要获取到真实email数据还要根据matches中的ID去搜索mysql的email表,但总体来说这样一来一回的速度还是远远比mysql的LIKE快得多,前提是几十万数据量以上, 否则用sphinx只会更慢。
接下来介绍sphinx一些类似mysql条件的用法
//emailid的范围
$sphinx->SetIdRange($min, $max);
//属性过滤,可过滤的属性必需在配置文件中设置sql_attr_ ,之前我们定义了这些
sql_attr_uint = fromid
sql_attr_uint = toid
sql_attr_timestamp = sendtime
//如果你想再次修改这些属性,配置完成后记得重新建立索引才能生效
//指定一些值
$sphinx->SetFilter('fromid', array(1,2)); //fromid的值只能是1或者2
//和以上条件相反,可增加第三个参数
$sphinx->SetFilter('fromid', array(1,2), false); //fromid的值不能是1或者2
//指定一个值的范围
$sphinx->SetFilterRange('toid', 5, 200); //toid的值在5-200之间
//和以上条件相反,可增加第三个参数
$sphinx->SetFilterRange('toid', 5, 200, false); //toid的值在5-200以外
//执行搜索
$result = $sphinx->query('关键字', '*');
排序模式
可使用如下模式对搜索结果排序:
SPH_SORT_RELEVANCE 模式, 按相关度降序排列(最好的匹配排在最前面)
SPH_SORT_ATTR_DESC 模式, 按属性降序排列 (属性值越大的越是排在前面)
SPH_SORT_ATTR_ASC 模式, 按属性升序排列(属性值越小的越是排在前面)
SPH_SORT_TIME_SEGMENTS 模式, 先按时间段(最近一小时/天/周/月)降序,再按相关度降序
SPH_SORT_EXTENDED 模式, 按一种类似SQL的方式将列组合起来,升序或降序排列。
SPH_SORT_EXPR 模式,按某个算术表达式排序
//使用属性排序
//以fromid倒序排序,注意当再次使用SetSortMode会覆盖上一个排序
$sphinx->SetSortMode ( "SPH_SORT_ATTR_DESC", 'fromid');
//如果要使用多个字段排序可使用SPH_SORT_EXTENDED模式
//@id是sphinx内置关键字,这里指emailid,至于为什么是emailid,自己思考一下
$sphinx->SetSortMode ( "SPH_SORT_ATTR_DESC", 'fromid ASC, toid DESC, @id DESC');
//执行搜索
$result = $sphinx->query('关键字', '*');
//更多请查看官方文档排序模式的说明
匹配模式
有如下可选的匹配模式:
SPH_MATCH_ALL, 匹配所有查询词(默认模式);
SPH_MATCH_ANY, 匹配查询词中的任意一个;
SPH_MATCH_PHRASE, 将整个查询看作一个词组,要求按顺序完整匹配;
SPH_MATCH_BOOLEAN, 将查询看作一个布尔表达式
SPH_MATCH_EXTENDED, 将查询看作一个CoreSeek/Sphinx内部查询语言的表达式 . 从版本Coreseek 3 /Sphinx 0.9.9开始, 这个选项被选项SPH_MATCH_EXTENDED2代替,它提供了更多功能和更佳的性能。保留这个选项是为了与遗 留的旧代码兼容——这样即使Sphinx及其组件包括API升级的时候,旧的应用程序代码还能够继续工作。
SPH_MATCH_EXTENDED2, 使用第二版的“扩展匹配模式”对查询进行匹配.
SPH_MATCH_FULLSCAN, 强制使用下文所述的“完整扫描”模式来对查询进行匹配。注意,在此模式下,所有的查询词都被忽略,尽管过滤器、过滤器范围以及分组仍然起作用,但任何文本匹配都不会发生.
我们要关注的主要是SPH_MATCH_EXTENDED2扩展匹配模式,扩展匹配模式允许使用一些像mysql的条件语句
//设置扩展匹配模式
$sphinx->SetMatchMode ( "SPH_MATCH_EXTENDED2" );
//查询中使用条件语句,字段用@开头,搜索内容包含测试,toid等于1的邮件:
$result = $sphinx->query('@content (测试) & @toid =1', '*');
//用括号和&(与)、|、(或者)、-(非,即!=)设置更复杂的条件
$result = $sphinx->query('(@content (测试) & @subject =呃) | (@fromid -(100))', '*');
//更多语法请查看官方文档匹配模式的说明
扩展匹配模式中值得一提的是搜索的字段,如果该字段被设置属性,那么扩展匹配搜索的字段默认是不包含这些属性的,只能用SetFilter()或者SetFilterRange()之类
之前我们设置了fromid、toid、sendtime为属性,但又想在扩展匹配模式中又想用作条件该怎么办?
只要在sql_query语句中再选择多一次该字段就可以了
sql_query = SELECT emailid,fromid,fromid,toid,toid,subject,content,sendtime,sendtime,attachement FROM email
//设置完成记得重新建立索引
更多条件技巧
只是一些技巧,但不建议使用的部署环境中,至于为什么,请看文章结尾
<、<=、>、>=
默认sphinx没有这些比较符。
假如我想邮件的发送时间大于某一日期怎么办?用SetFilterRange()方法模拟一下
//大于等于某一时间截$time
$sphinx->SetFilterRange('sendtime', $time, 10000000000) //时间截最大是10个9,再加1是不可超越了。。
//大于某一时间截$time
$sphinx->SetFilterRange('sendtime', $time+1, 10000000000)
//小于等于某一时间截$time
$sphinx->SetFilterRange('sendtime', -1, $time) //时间截最小是0,所以应该减1
//大于某一时间截$time
$sphinx->SetFilterRange('sendtime', -1, $time - 1)
IS NOT NULL
怎样搜索为空的字段,比如我要搜索附件为空的邮件,有人可能会想 @attachment ('')不就可以了吗?其实这是搜索两个单引号。。。sphinx搜索的字符串不用加引号的
目前sphinx是没有提供这样的功能,其实可以在mysql语句上作手脚:
sql_query = SELECT emailid,fromid,toidsubject,content,sendtime,attachement != '' as attach is not null FROM email //这里返回了一个新字段attachisnotnull,当attachisnotnull为1的时候附件就不为空了
//设置完成记得重新建立索引
FIND_IN_SET()
搜索包含某一附件的邮件,mysql习惯用FIND_IN_SET这么简单一句就搞定了,在sphinx中必需在配置里设置属性sql_attr_multi 多值属性(MVA):
sql_attr_multi = attachment #attachment可以是逗号分隔的附件ID,或者是空格、分号等sphinx都能识别
//设置完成记得重新建立索引
然后PHP中可以使用SetFilter()
//搜索包含附件ID为1或2邮件,mysql语法是这样FIND_IN_SET(`attachment`, '1,2')
$sphinx->SetFilter('attachment', array(1,2))
//可以使用SetFilterRange,搜索包含附件ID在50-100范围的邮件
$sphinx->SetFilterRange('attachment', 50, 100)
Sphinx根据字段在字段内搜索
Controller
1. <?php
2. namespace app\controllers;
3.
4. use Yii;
5. use yii\web\Controller;
6. use app\models\Sphinx_much_search;
7. use SphinxClient;
8. class SearchController extends Controller
9. {
10. public $enableCsrfValidation = false;
11. public function actionLogin()
12. {
13. $db=new Sphinx_much_search;
14. $a=$db->find()->asArray()->all();
15. return $this->renderPartial('login');
16. }
17. public function actionSearch()
18. {
19. $field=\yii::$app->request->post('field');
20. $zhi=\yii::$app->request->post('zhi');
21. $sphinx= new SphinxClient();
22. $sphinx->SetServer('127.0.0.1',9312);
23. //将查询看作一个Sphinx内部查询语言的表达式
24. $sphinx->SetMatchMode ( SPH_MATCH_EXTENDED2 );
25. //@符号屏蔽错误 第一个参数中 $filed是字段名 $zhi是你要在这个字段中搜索的值 第二个参数是规则
26. $res=$sphinx->Query("@".$field.' '.$zhi,"mysql");
27. // array_keys是获取数组中的键(获取到的是一个数组) 然后将数组转换成字符串
28. $id=implode(',',array_keys($res['matches']));
29. $val=Sphinx_much_search::find()->where("id in ($id)")->asArray()->All();
30. //print_r($val);die;
31. foreach ($val as $k =>$v)
32. {
33. $val[$k]['title']=str_replace($zhi,"<font color='red'>$zhi</font>",$v['title']);
34. $val[$k]['content']=str_replace($zhi,"<font color='red'>$zhi</font>",$v['content']);
35. $val[$k]['country']=str_replace($zhi,"<font color='red'>$zhi</font>",$v['country']);
36. }
37. echo json_encode($val);
38. }
39. }
40. ?>
View
1. <!DOCTYPE html>
2. <html lang="en">
3. <head>
4. <meta charset="UTF-8">
5. <title>Document</title>
6. <script src="js/jq.js"></script>
7. </head>
8. <body>
9. <table align="center">
10. <tr>
11. <td>搜索字段</td>
12. <td>
13. <select id="field">
14. <option value="*">全部字段</option>
15. <option value="title">标题</option>
16. <option value="content">内容</option>
17. <option value="country">国家</option>
18. </select>
19. </td>
20. <td><input type="text" id="zhi"></td>
21. <td><input type="submit" class="fun" value="搜索"></td>
22. </tr>
23. <tr id="lists">
24. <td>标题</td>
25. <td>内容</td>
26. <td>国家</td>
27. </tr>
28. <tr class="contents"></tr>
29. </table>
30. </body>
31. </html>
32. <script>
33. $(".fun").click(function(){
34. var field=$("#field").val();
35. var zhi=$("#zhi").val();
36. $.post('?r=search/search',{'field':field,'zhi':zhi},function(msg){
37. //alert(msg);
38. var data=eval("("+msg+")");
39. var tr='';
40. for(i in data)
41. {
42. tr+='<tr class="contents">';
43. tr+="<td>"+data[i].title+"</td>"
44. tr+="<td>"+data[i].content+"</td>"
45. tr+="<td>"+data[i].country+"</td>"
46. tr+='</tr>';
47. }
48. $(".contents").remove();
49. $("#lists").after(tr);
50. })
51. })
52. </script>
总结
如果你想一个免费、好用、极速的全文搜索引擎,sphinx无疑是最好的选择,但是不要忘记sphinx的目的:全文检索。不要去想那些乱七八糟条件。你 想要把sphinx搜索变得像mysql那样灵活,可完全单独用在一些复杂的多条件搜索,像某些邮件的高级搜索,那么我建议你还是多花点时间在PHP或者mysql代码的优化上,因为那样可能会让你的搜索变得更慢。
最好的方法是以最简单的方法搜索到内容,将ID交还mysql数据库搜索。