2011-08-19 102 views
6

我很新MySQL的全文搜索,我今天就遇到了這個問題:MySQL的布爾模式的全文搜索使用通配符和文字

我公司表中有「電子雜誌AG」的記錄中名稱列。我在名稱列上有一個全文索引。

當我執行這個查詢記錄中沒有找到:

SELECT id, name FROM company WHERE MATCH(name) AGAINST('+"e-magazi"*' IN BOOLEAN MODE); 

我需要由於儀表板的報價工作,因爲我實現了一個「搜索您的輸入」功能,使用通配符。

當我搜索整個術語「電子雜誌AG」時,找到了該記錄。

任何想法我在做什麼錯在這裏?我讀到了有關將字符添加到單詞字符列表(需要配置更新)的問題,但我正在尋找一種以編程方式執行此操作的方法。

+0

有趣的問題。我可以在這裏用一個像uuid字段的表格複製它。 'SELECT id,bootid FROM socket WHERE MATCH(bootid)AGAINST('+「18bda775」'BOOLEAN MODE);'會工作,如果我搜索「18bda775-711c」,但搜索「18bda」或「18bda775 -711「不起作用。有問題的'bootid'字段包含:18bda775-711c-4329-9de2-a3d81dc13d06 –

+0

我們也試圖改變布爾控制字符,而不是使用# - 但它沒有任何效果(是的,我修好了變更後的表索引) :'ft_boolean_syntax = +#><()〜*:「」&|' – hajo

回答

2

這一條款

MATCH(name) AGAINST('+"e-magazi"*' IN BOOLEAN MODE); 

將搜索AND "e" AND NOT "magazi";即「e-magazi」中的-將被解釋爲not,即使它在引號內。
由於這個原因,它不會按預期工作。
一個解決方案是使用一個LIKE來應用一個額外的having子句。

我知道這having是慢的,但它只會應用於匹配的結果,所以不應該涉及太多的行。

我建議是這樣的:

SELECT id, name 
FROM company 
WHERE MATCH(name) AGAINST('magazine' IN BOOLEAN MODE) 
HAVING name LIKE '%e-magazi%'; 
+0

感謝您的信息,但它不幫助我,因爲搜索字符串是由想要搜索公司的用戶輸入的。換句話說,執行查詢的後端無法知道「e-magazi」是字符串「電子雜誌」的一部分。搜索字段應該接受單詞部分和完整單詞。 – hajo

+0

過濾方法非常獨特的方法!謝謝! – ProfileTwist

+0

你在哪裏看到前面或搜索詞組後的空白處? '+'是一個常規的全文操作符,而不是一個空格! – mgutt

0

MySQL的全文對待文本作爲短語作爲一個詞的詞e-magazine。因爲它導致兩個單詞emagazine。雖然它建立搜索索引,但它不會將e添加到索引,因爲ft_min_word_len(默認值爲4個字符)。

搜索查詢使用相同的長度限制。這就是爲什麼搜索e-magazine返回的結果與a-magazine完全相同的原因,因爲a-被完全忽略。

但現在你想找到確切的短語e-magazine。通過您使用引號,那就是找到短語完全正確的方法,但MySQL不支持運營商的短語,只爲一句話:
https://dev.mysql.com/doc/refman/5.7/en/fulltext-boolean.html

有了這個修改,某些字符具有特殊意義開始的時候還是在搜索字符串結束

有些人會建議使用以下查詢:

SELECT id, name 
FROM company 
WHERE MATCH(name) AGAINST('e-magazi*' IN BOOLEAN MODE) 
HAVING name LIKE 'e-magazi%'; 

正如我所說的MySQL忽略e-並搜索通配詞magazi*。在獲得這些結果後,它使用HAVING對​​的結果進行過濾,包括e-。通過這你會發現短語e-magazine AG。當然,只有當搜索短語包含通配符運算符時,才需要使用HAVING,並且不應使用引號。這個操作符被你的用戶使用,而不是你!

注:只要你不圍繞搜索短語與%它會發現只有以該字開始的字段。而且你不想圍繞它,因爲它也會找到bee-magazine。所以也許你需要額外的OR HAVING name LIKE ' %e-magazi%' OR HAVING NAME LIKE '\\n%e-magazi%'才能在文本中使用它。

招數

但最後我更喜歡這樣是不是需要在所有一招HAVING

  1. 如果添加文本到您的數據庫表,另外將它們添加到一個單獨的全文索引的列並用up-to-date uptodate替換up-to-date等詞。
  2. 如果up-to-date用戶搜索與uptodate取代它在查詢中。

通過,你仍然可以找到user-specificspecificup-to-date以及(不僅date)。

獎金

如果-well-known huge ports MySQL的用戶搜索把它僞裝成not include *well*, could include *known* and *huge*。當然你可以解決與其他額外的查詢變型爲好,但你上面的伎倆刪除連字符因此搜索查詢看起來簡直像:

SELECT id 
FROM texts 
WHERE MATCH(text) AGAINST('-wellknown huge ports' IN BOOLEAN MODE)