sphinx全文检索之PHP应用教程

    添加时间:2013-5-4 点击量:

    这是半年前没有对外写的文章,如今拿出来分享下。可能会有一些不正确或不严谨的处所,某些说话可能斗劲轻浮,请见谅。



    上一篇[查看]介绍了sphinx的根蒂根基安装、设备和应用,如今来看看如何应用在PHP上。




    根蒂根基


    以上一篇的email数据表为例:


    数据布局



    CREATE TABLE email (
    
    emailid mediumint(
    8) unsigned NOT NULL auto_increment COMMENT 邮件id

    id
    int10) unsigned NOT NULL default 0 COMMENT 发送人ID

    toid
    int10) unsigned NOT NULL default 0 COMMENT 收件人ID
    content
    text unsigned NOT NULL COMMENT 邮件内容
    subject
    varchar100) unsigned NOT NULL COMMENT 邮件题目

    sendtime
    int10NOT NULL COMMENT 发送时候

    attachment
    varchar100NOT 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数据库搜刮。




    文艺不是炫耀,不是花哨空洞的文字堆砌,不是一张又一张的逆光照片,不是将旅行的意义转化为名牌包和明信片的物质展示;很多时候它甚至完全不美——它嘶吼、扭曲,它会痛苦地抽搐,它常常无言地沉默。——艾小柯《文艺是一种信仰》
    分享到: