2012-02-04 95 views
0

嗨我有一個大問題,一個MYSQL搜索。 我的數據庫表看起來像這樣:如何讓MYSQL搜索最少3個關鍵字匹配?

+------+----------+------+ 
| id | keywords | file | 
+------+----------+------+ 

在關鍵詞有與昏迷分隔每個條目的關鍵字。 (關鍵詞1,關鍵詞......)。

在PHP數組中列出了一些關鍵字(5-10)。 而我的搜索必須獲得所有關鍵字至少3的數據庫條目。 它不需要得到所有這些單詞!但它不能工作,只有一個。

有人可以幫我解決這個問題嗎?我不知道如何做到這一點。

+0

那麼什麼是你的其他的表結構看起來就像你正在尋找對抗......或者是這樣的吧,你只是用一個字符串來比較。如果是這樣,關鍵字上下文設計不佳。 – DRapp 2012-02-04 17:11:30

+0

還沒有其他表。我必須在現場搜索:關鍵字。 – Svetoslav 2012-02-04 17:14:53

+4

@Svetlio:表格結構是您的選擇嗎?你是如何使用逗號分隔值列來的?如果你看過這將是良好[規範化](http://en.wikipedia.org/wiki/Database_normalization),並在關係表中存儲逗號分隔值的問題:是存儲一個逗號數據庫中的列分隔列表真那壞?](http://stackoverflow.com/questions/3653462/is-storing-a-comma-separated-list-in-a-database-column-really-that-bad) – 2012-02-04 17:34:11

回答

2

這是一個挑戰。暴力方法是在一個帶有計數的子查詢中使用UNION。

例如,

select id, file, count(*) from 
    (select distinct id, file 
    from file_table 
     where FIND_IN_SET(keyword1, keywords) 
    UNION ALL 
    select distinct id, file 
    from file_table 
     where FIND_IN_SET(keyword2, keywords) 
    UNION ALL 
    select distinct id, file 
    from file_table 
     where FIND_IN_SET(keyword3, keywords) 
    UNION ALL 
    select distinct id, file 
    from file_table 
     where FIND_IN_SET(keyword4, keywords) 
    .... MORE UNION ALL ....) as files 
group by id, file 
having count(*) >= 3 

更有效,你可以有關鍵字和ID,一個關鍵字/每行ID組合一個單獨的表。這將消除通配符搜索並使查詢更有效。

接下來的步驟是去ElasticSearch之類的東西,並過濾結果的分數。

+0

所以,如果你搜索關鍵字'男人',它也會計算關鍵字'女人','男人','鬃毛'和'許多'...更多 – 2012-02-04 17:21:41

+0

沒有說這是一個很好的解決方案。只是它會起作用。該解決方案將是確保每一個關鍵字後綴有一個「」這樣的關鍵詞可能是‘女人,男人,男子漢氣概,鬃毛’,然後修改查詢每次放在後面的逗號。 – 2012-02-04 17:28:19

+0

是的。你也可以使用'FIND_IN_SET()'函數來識別逗號分隔值。但是,通過按照您的建議製作多對多表格來正常化結構**是正確的方法。所有其他人都是詭計。 – 2012-02-04 17:29:57

0

如果你有這樣的設置:

表文件:

+------+-------+ 
| id | file | 
+------+-------+ 
| 1000 | foo | 
| 1001 | bar | 
+------+-------+ 

表關鍵字:

​​

表filekeywords:

+----+--------+--------+ 
| id | fileid | wordid | 
+----+--------+--------+ 
| 1 | 1000 | 9  | 
| 2 | 1000 | 10  | 
| 3 | 1001 | 10  | 
+----+--------+--------+ 

你可以找到關鍵字的文件loremipsumdolor這樣的:

SELECT COUNT(DISTINCT(k.word)), f.* 
FROM files f 
INNER JOIN filekeywords fk 
    ON fk.fileid = f.id 
INNER JOIN keywords k 
    ON k.id = fk.wordid 
WHERE k.word in ('lorem', 'ipsum', 'dolor') 
GROUP BY f.id 
HAVING COUNT(DISTINCT(k.word)) >= 3