sphinx全文檢索之PHP使用(轉)

基礎

數據結構:php

	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';

 

 

使用打開控制檯,必需打開控制檯PHP才能鏈接到sphinx(確保你已經創建好索引源):mysql

d:\coreseek\bin\searchd -c d:\coreseek\bin\sphinx.confweb

 

coreseek/api目錄下提供了PHP的接口文件 sphinxapi.php,這個文件包含一個SphinxClient的類sql

在PHP引入這個文件,new一下數據庫

01 $sphinx = new SphinxClient();
02  
03 //sphinx的主機名和端口
04  
05 $sphinx->SetServer ( 'loclahost', 9312 );
06  
07 //設置返回結果集爲php數組格式
08  
09 $sphinx->SetArrayResult ( true );
10  
11 //匹配結果的偏移量,參數的意義依次爲:起始位置,返回結果條數,最大匹配條數
12  
13 $sphinx->SetLimits(0, 20, 1000);
14  
15 //最大搜索時間
16  
17 $sphinx->SetMaxQueryTime(10);
18  
19  
20  
21 //執行簡單的搜索,這個搜索將會查詢全部字段的信息,要查詢指定的字段請繼續看下文
22  
23 $index = 'email' //索引源是配置文件中的 index 類,若是有多個索引源可以使用,號隔開:'email,diary' 或者使用'*'號表明所有索引源
24  
25 $result = $sphinx->query ('搜索關鍵字', $index);
26  
27 echo '<pre>';
28  
29 print_r($result);
30  
31 echo '</pre>';

 

$result是一個數組,其中api

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條件的用法

01 //emailid的範圍
02  
03 $sphinx->SetIdRange($min, $max);
04  
05  
06  
07 //屬性過濾,可過濾的屬性必需在配置文件中設置sql_attr_    ,以前咱們定義了這些
08  
09     sql_attr_uint            = fromid
10  
11     sql_attr_uint            = toid
12  
13     sql_attr_timestamp  = sendtime
14  
15 //若是你想再次修改這些屬性,配置完成後記得從新創建索引才能生效
16  
17  
18  
19 //指定一些值
20  
21 $sphinx->SetFilter('fromid', array(1,2));    //fromid的值只能是1或者2
22  
23 //和以上條件相反,可增長第三個參數
24  
25 $sphinx->SetFilter('fromid', array(1,2), false);    //fromid的值不能是1或者2
26  
27 //指定一個值的範圍
28  
29 $sphinx->SetFilterRange('toid', 5, 200);    //toid的值在5-200之間
30  
31 //和以上條件相反,可增長第三個參數
32  
33 $sphinx->SetFilterRange('toid', 5, 200, false);    //toid的值在5-200之外
34  
35  
36  
37 //執行搜索
38  
39 $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 模式,按某個算術表達式排序

01 //使用屬性排序
02  
03 //以fromid倒序排序,注意當再次使用SetSortMode會覆蓋上一個排序
04  
05 $sphinx->SetSortMode ( "SPH_SORT_ATTR_DESC", 'fromid');
06  
07 //若是要使用多個字段排序可以使用SPH_SORT_EXTENDED模式
08  
09 //@id是sphinx內置關鍵字,這裏指emailid,至於爲何是emailid,本身思考一下
10  
11 $sphinx->SetSortMode ( "SPH_SORT_ATTR_DESC", 'fromid ASC, toid DESC, @id DESC');
12  
13 //執行搜索
14  
15 $result = $sphinx->query('關鍵字', '*');
16  
17 //更多請查看官方文檔排序模式的說明

 

 

匹配模式

有以下可選的匹配模式:

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的條件語句

01 //設置擴展匹配模式
02  
03 $sphinx->SetMatchMode ( "SPH_MATCH_EXTENDED2" );
04  
05 //查詢中使用條件語句,字段用@開頭,搜索內容包含測試,toid等於1的郵件:
06  
07 $result = $sphinx->query('@content (測試) & @toid =1', '*');
08  
09 //用括號和&(與)、|、(或者)、-(非,即!=)設置更復雜的條件
10  
11 $result = $sphinx->query('(@content (測試) & @subject =呃) | (@fromid -(100))', '*');
12  
13 //更多語法請查看官方文檔匹配模式的說明

 

擴展匹配模式中值得一提的是搜索的字段,若是該字段被設置屬性,那麼擴展匹配搜索的字段默認是不包含這些屬性的,只能用SetFilter()或者SetFilterRange()之類

以前咱們設置了fromid、toid、sendtime爲屬性,但又想在擴展匹配模式中又想用做條件該怎麼辦?

只要在sql_query語句中再選擇多一次該字段就能夠了

sql_query                = SELECT emailid,fromid,fromid,toid,toid,subject,content,sendtime,sendtime,attachement FROM email

//設置完成記得從新創建索引

 

 

更多條件技巧

只是一些技巧,但不建議使用的部署環境中,至於爲何,請看文章結尾

 

<、<=、>、>=

默認sphinx沒有這些比較符。

假如我想郵件的發送時間大於某一日期怎麼辦?用SetFilterRange()方法模擬一下

 

01 //大於等於某一時間截$time
02  
03 $sphinx->SetFilterRange('sendtime', $time, 10000000000) //時間截最大是10個9,再加1是不可超越了。。
04  
05  
06  
07 //大於某一時間截$time
08  
09 $sphinx->SetFilterRange('sendtime', $time+1, 10000000000)
10  
11 //小於等於某一時間截$time
12  
13 $sphinx->SetFilterRange('sendtime', -1, $time)    //時間截最小是0,因此應該減1
14  
15 //大於某一時間截$time
16  
17 $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()

1 //搜索包含附件ID爲1或2郵件,mysql語法是這樣FIND_IN_SET(`attachment`, '1,2')
2  
3 $sphinx->SetFilter('attachment', array(1,2))
4  
5 //能夠使用SetFilterRange,搜索包含附件ID在50-100範圍的郵件
6  
7 $sphinx->SetFilterRange('attachment', 50, 100)

 

 

總結

若是你想一個免費、好用、極速的全文搜索引擎,sphinx無疑是最好的選擇,可是不要忘記sphinx的目的:全文檢索。不要去想那些亂七八糟條件。你想要把sphinx搜索變得像mysql那樣靈活,可徹底單獨用在一些複雜的多條件搜索,像某些郵件的高級搜索,那麼我建議你仍是多花點時間在PHP或者mysql代碼的優化上,由於那樣可能會讓你的搜索變得更慢。

最好的方法是以最簡單的方法搜索到內容,將ID交還mysql數據庫搜索。

相關文章
相關標籤/搜索