關於多屬性查找問題的sphinx解決方案


需求描述

mysql中,每一個文檔都有多個標簽,查詢時可以篩選一個標簽也可以篩選同時擁有多個標簽的文檔。

數據示例

文檔         標簽
1             1,2,3,4,5
2             2,3,4,5,6
3             3,4,5,6,7
4             4,5,6,7,8
5             5,6,7,8,9

注意:
這里將文檔id和標簽tagid的對應關系存入了fy_content_tag表,一個id對應多條tagid記錄

查詢要求

1、查出擁有標簽2的文檔
2、查出同時擁有標簽2,3,4的文檔

使用sphinx解決需求

1、配置shpinx mva多值屬性

編輯sphinx配置文件,給數據源增加一個多值屬性

sql_attr_multi = uint tagid from query;\
       SELECT id,tagid FROM fy_content_tag

2、執行查詢

使用API中的setFilter即可。

1、查出擁有標簽2的文檔

$sphinx->setFilter('tagid', array(2));

2、查出同時擁有標簽2,3,4的文檔

$sphinx->setFilter('tagid', array(2));
$sphinx->setFilter('tagid', array(3));
$sphinx->setFilter('tagid', array(4));

這里解釋一下:
$sphinx->setFilter(‘tagid’, array(2,3,4));
是表示含有標簽值2,3,4中的任意一個即符合篩選,這里是or關系。

$sphinx->setFilter(‘tagid’, array(2));
$sphinx->setFilter(‘tagid’, array(3));
$sphinx->setFilter(‘tagid’, array(4));
設置三個filter是標示,要同時滿足2,3,4三個屬性值才符合,這里是and關系。

————————————

Sphinx sql_attr_multi配置參考

在Sphinx中,有一個MVA屬性,聲明格式如下(用反斜線只是為了清晰,您仍可以在一行之內完成聲明):
sql_attr_multi = ATTR-TYPE ATTR-NAME ‘from’ SOURCE-TYPE \
[;QUERY] \
[;RANGE-QUERY]
其中
ATTR-TYPE 是 ‘uint’ 或 ‘timestamp’之一
SOURCE-TYPE 是 ‘field’, ‘query’, 或 ‘ranged-query’之一
QUERY 是用來取得全部(文檔 ID,屬性值)序對的 SQL 查詢
RANGE-QUERY 是用來取得文檔 ID 的最小值與最大值的 SQL 查詢,
與’sql_query_range’類似
示例:
sql_attr_multi = uint tag from field;
sql_attr_multi = uint tag from query; SELECT id, tag FROM tags
sql_attr_multi = uint tag from ranged-query; \
SELECT id, tag FROM tags WHERE id>=$start AND id<=$end; \
SELECT MIN(id), MAX(id) FROM tags

使用field類型時,field字段的值應該是以英文逗號隔開的多個無符號32位整數,如:1,2,3,4

使用query或者ranged-query時,每行一個值,一個id對應多個(多行)tag值

 

上面講的都是一些理論,實際工作中我們不需要再創建一張表,而是增加一個字段就可以了:

Sphinx MVA(聲明多值屬性)的用法
最近開始學習Sphinx,於是安裝了“Coreseek 全文檢索服務器 2.0“,詳情可訪問Coreseek官網,喬老大真的很熱心,有問題可以POST在BBS,也可以加他的MSN,他都會耐心的為你解答,真是難得的好人。
  回到主題,在Mysql數據庫中,有SET(集合)類型,可以保存多個值,使用FIND_IN_SET函數查找也很方便。在使用Sphinx中,有一個MVA屬性,聲明格式如下(用反斜線只是為了清晰,您仍可以在一行之內完成聲明):
sql_attr_multi = ATTR-TYPE ATTR-NAME 'from' SOURCE-TYPE \
[;QUERY] \
[;RANGE-QUERY]
其中
ATTR-TYPE 是 ‘uint’ 或 ‘timestamp’之一
SOURCE-TYPE 是 ‘field’, ‘query’, 或 ‘ranged-query’之一
QUERY 是用來取得全部(文檔 ID,屬性值)序對的 SQL 查詢
RANGE-QUERY 是用來取得文檔 ID 的最小值與最大值的 SQL 查詢,
與’sql_query_range’類似
示例:
sql_attr_multi = uint tag from field;
sql_attr_multi = uint tag from query; SELECT id, tag FROM tags
sql_attr_multi = uint tag from ranged-query; \
SELECT id, tag FROM tags WHERE id>=$start AND id<=$end; \
SELECT MIN(id), MAX(id) FROM tags
使用第一種還是比較方便,由於沒有說明,當時也試了很久,字段值的存放格式是:
| tag |
|1,2,3,4,5,6|
使用field類型,就可以實現了。這里的分隔符不僅僅可以使用逗號,還可以使用空格,或者其他字符,如:
| tag |
|1%3%14 60|
Sphix也是可以識別的,不過,還是統一用分隔符比較好。^-^

 

 

如何在sphinxse中使用?

在sphinxSE中用WHERE query='filter=ids,2345,5334' 即可實現SQL中WHERE ids IN (2345,5334)的效果。

 

修改sphinx最大輸出記錄數

歸納如下:
Sphinx的查詢默認最大記錄數是:1000,而我們想更改這個數值。就需要更改三個地方。
1是更改sphinx.conf配置文件的:max_matches   = 10000 #后面數字就是你想查詢的最大記錄數。建議在1000~10000之內。
2是在api調用時,$cl->SetLimits($pageStart, $pageSize, $max_limits);用SetLimits的第三個參數更改為你想要的顯示最大記錄數。
3 修改sphinxclient.php 中max_matches
 
問題是這樣的,信息列表頁的分頁里顯示有100多頁,但到51頁的時候不顯示正確的信息列表了。按慣例,輸出結果,查看可疑之處。發現返回的結果里total永遠都是1000,total_found大概是分頁中顯示的頁數和每頁信息數的乘積,這說明total_found返回的是真正的信息數,但查詢結果的時候又受到了total的限制。
百度sphinx total_found,得知sphinx有個max_matches是限制匹配結果數的,看了sphinx.conf,發現其中設置的max_matches遠大於查詢結果數,看來代碼中有設置了,又查看sphinx的應用類,發現了SetLimits($start, $limit, 1000)這個東東,原來max_matches在這兒被定成了1000。
據說max_matches設定太大的話,查詢速度會受影響,想了想把這個值設成變量,等於要查詢的頁數和每頁信息數的乘積,這樣就能得到正確的結果了,而且不會影響小頁碼的頁面原查詢速度。
http://www.ourjour.com/tag/sphinx-max_matches/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM