sphinx全文检索之PHP应用教程
添加时间:2013-5-4 点击量:
这是半年前没有对外写的文章,如今拿出来分享下。可能会有一些不正确或不严谨的处所,某些说话可能斗劲轻浮,请见谅。
上一篇[查看]介绍了sphinx的根蒂根基安装、设备和应用,如今来看看如何应用在PHP上。
根蒂根基
以上一篇的email数据表为例:
数据布局:
CREATE TABLE email (
emailid mediumint(8) unsigned NOT NULL auto_increment COMMENT 邮件id,
id 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;
应用打开把握台,必须打开把握台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 ( loclahost, 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,id,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 = id
sql_attr_uint = toid
sql_attr_timestamp = sendtime
//若是你想再次批改这些属性,设备完成跋文得从头建树索引才干生效
//指定一些值
¥sphinx->SetFilter(id, array(1,2)); //id的值只能是1或者2
//和以上前提相反,可增长第三个参数
¥sphinx->SetFilter(id, array(1,2), false); //id的值不克不及是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 模式,按某个算术表达式排序
//应用属性排序
//以id倒序排序,重视当再次应用SetSortMode会覆盖上一个排序
¥sphinx->SetSortMode ( SPH_SORT_ATTR_DESC, id);
//若是要应用多个字段排序可应用SPH_SORT_EXTENDED模式
//@id是sphinx内置关键字,这里指emailid,至于为什么是emailid,本身思虑一下
¥sphinx->SetSortMode ( SPH_SORT_ATTR_DESC, id 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 =呃) | (@id -(100)), );
//更多语法请查看官方文档匹配模式的申明
扩大匹配模式中值得一提的是搜刮的字段,若是该字段被设置属性,那么扩大匹配搜刮的字段默认是不包含这些属性的,只能用SetFilter()或者SetFilterRange()之类
之前我们设置了id、toid、sendtime为属性,但又想在扩大匹配模式中又想用作前提该怎么办?
只要在sql_query语句中再选择多一次该字段就可以了
sql_query = SELECT emailid,id,id,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,id,toidsubject,content,sendtime,attachement != as attachisnotnull 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无疑是好的选择,然则不要忘怀sphinx的目标:全文检索。不要去想那些东倒西歪前提。你想要把sphinx搜刮变得像mysql那样灵活,可完全零丁用在一些错杂的多前提搜刮,像某些邮件的高等搜刮,那么我建议你还是多花点时候在PHP或者mysql代码的优化上,因为那样可能会让你的搜刮变得更慢。
好的办法是以最简单的办法搜刮到内容,将ID交还mysql数据库搜刮。
文艺不是炫耀,不是花哨空洞的文字堆砌,不是一张又一张的逆光照片,不是将旅行的意义转化为名牌包和明信片的物质展示;很多时候它甚至完全不美——它嘶吼、扭曲,它会痛苦地抽搐,它常常无言地沉默。——艾小柯《文艺是一种信仰》
这是半年前没有对外写的文章,如今拿出来分享下。可能会有一些不正确或不严谨的处所,某些说话可能斗劲轻浮,请见谅。
上一篇[查看]介绍了sphinx的根蒂根基安装、设备和应用,如今来看看如何应用在PHP上。
根蒂根基
以上一篇的email数据表为例:
数据布局:
CREATE TABLE email (
emailid mediumint(8) unsigned NOT NULL auto_increment COMMENT 邮件id,
id 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;
应用打开把握台,必须打开把握台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 ( loclahost, 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,id,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 = id
sql_attr_uint = toid
sql_attr_timestamp = sendtime
//若是你想再次批改这些属性,设备完成跋文得从头建树索引才干生效
//指定一些值
¥sphinx->SetFilter(id, array(1,2)); //id的值只能是1或者2
//和以上前提相反,可增长第三个参数
¥sphinx->SetFilter(id, array(1,2), false); //id的值不克不及是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 模式,按某个算术表达式排序
//应用属性排序
//以id倒序排序,重视当再次应用SetSortMode会覆盖上一个排序
¥sphinx->SetSortMode ( SPH_SORT_ATTR_DESC, id);
//若是要应用多个字段排序可应用SPH_SORT_EXTENDED模式
//@id是sphinx内置关键字,这里指emailid,至于为什么是emailid,本身思虑一下
¥sphinx->SetSortMode ( SPH_SORT_ATTR_DESC, id 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 =呃) | (@id -(100)), );
//更多语法请查看官方文档匹配模式的申明
扩大匹配模式中值得一提的是搜刮的字段,若是该字段被设置属性,那么扩大匹配搜刮的字段默认是不包含这些属性的,只能用SetFilter()或者SetFilterRange()之类
之前我们设置了id、toid、sendtime为属性,但又想在扩大匹配模式中又想用作前提该怎么办?
只要在sql_query语句中再选择多一次该字段就可以了
sql_query = SELECT emailid,id,id,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,id,toidsubject,content,sendtime,attachement != as attachisnotnull 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无疑是好的选择,然则不要忘怀sphinx的目标:全文检索。不要去想那些东倒西歪前提。你想要把sphinx搜刮变得像mysql那样灵活,可完全零丁用在一些错杂的多前提搜刮,像某些邮件的高等搜刮,那么我建议你还是多花点时候在PHP或者mysql代码的优化上,因为那样可能会让你的搜刮变得更慢。
好的办法是以最简单的办法搜刮到内容,将ID交还mysql数据库搜刮。
文艺不是炫耀,不是花哨空洞的文字堆砌,不是一张又一张的逆光照片,不是将旅行的意义转化为名牌包和明信片的物质展示;很多时候它甚至完全不美——它嘶吼、扭曲,它会痛苦地抽搐,它常常无言地沉默。——艾小柯《文艺是一种信仰》