coreseek/api目錄下提供了PHP的接口文件 sphinxapi.php,這個文件包含一個SphinxClient的類php
在PHP引入這個文件,new一下mysql
$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是一個數組,其中sql
total是匹配到的數據總數量數據庫
matches是匹配的數據,包含id,attrs這些信息api
words是搜索關鍵字的分詞數組
你可能奇怪爲何沒有郵件的內容這些信息,其實sphinx並不會返回像mysql那樣的數據數組,由於sphinx原本就沒有記錄完整的數據,只記錄被分詞後的數據。性能
具體還要看matches數組,matches中的ID就是指配置文件中sql_query SELECT語句中的第一個字段,咱們配置文件中是這樣的測試
sql_query = SELECT emailid,fromid,toid,subject,content,sendtime,attachement FROM email優化
因此matches中的ID是指emailidui
至於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)
怎樣搜索爲空的字段,好比我要搜索附件爲空的郵件,有人可能會想 @attachment ('')不就能夠了嗎?其實這是搜索兩個單引號。。。sphinx搜索的字符串不用加引號的
目前sphinx是沒有提供這樣的功能,其實能夠在mysql語句上做手腳:
sql_query = SELECT emailid,fromid,toidsubject,content,sendtime,attachement != '' as attach is not null FROM email //這裏返回了一個新字段attachisnotnull,當attachisnotnull爲1的時候附件就不爲空了
//設置完成記得從新創建索引
搜索包含某一附件的郵件,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數據庫搜索。