為什麼全文搜尋返回的行數少於 LIKE
我沒有讓全文搜尋按我的意願工作,而且我不理解結果列表中的差異。
範例語句:
SELECT `meldungstext` FROM `artikel` WHERE `meldungstext` LIKE '%punkt%'
返回 92 行。我收到了匹配的行,例如,meldungstext 列中的“Punkten”、“Zwei-Punkte-Vorsprung”和“Treffpunkt”。
我在“meldungstext”列上設置了全文索引並嘗試了這個:
SELECT `meldungstext` FROM `artikel` WHERE MATCH (`meldungstext`) AGAINST ('*punkt*')
這僅返回 8 行。我只收到與“Punkt”本身匹配的行或我認為在“i-Punkt”中被視為“Punkt”的單詞。
然後我嘗試了布爾模式:
SELECT `meldungstext` FROM `artikel` WHERE MATCH (`meldungstext`) AGAINST ('*punkt*' IN BOOLEAN MODE)
返回 44 行。我收到的行在meldungstext 列中有“Zwei-Punkte-Vorsprung”或“Treffpunkt”,但沒有“Punkten”。
為什麼會發生這種情況,如何設置“完全”工作的全文搜尋以防止在 where 子句中使用 LIKE ‘%%’?
我把你問題中的三個字元串添加到一個表格中,再加上三個字元串,
pankt
而不是punkt
.以下是使用 MySQL 5.5.12 for Windows 執行的
mysql> CREATE TABLE artikel -> ( -> id INT NOT NULL AUTO_INCREMENT, -> meldungstext MEDIUMTEXT, -> PRIMARY KEY (id), -> FULLTEXT (meldungstext) -> ) ENGINE=MyISAM; Query OK, 0 rows affected (0.03 sec) mysql> INSERT INTO artikel (meldungstext) VALUES -> ('Punkten'),('Zwei-Punkte-Vorsprung'),('Treffpunkt'), -> ('Pankten'),('Zwei-Pankte-Vorsprung'),('Treffpankt'); Query OK, 6 rows affected (0.00 sec) Records: 6 Duplicates: 0 Warnings: 0 mysql>
我使用 3 種不同的方法對錶執行這些查詢
MATCH ... AGAINST
LOCATE
如在LOCATE函式中LIKE
請注意差異
mysql> SELECT id,meldungstext, -> COUNT(IF(MATCH (`meldungstext`) AGAINST ('*punkt*' IN BOOLEAN MODE),1,0)) PunktMatch, -> IF(LOCATE('punkt',meldungstext)>0,1,0) PunktLocate, -> meldungstext LIKE '%punkt%' PunktLike -> FROM `artikel` GROUP BY id,meldungstext; +----+-----------------------+------------+-------------+-----------+ | id | meldungstext | PunktMatch | PunktLocate | PunktLike | +----+-----------------------+------------+-------------+-----------+ | 1 | Punkten | 1 | 1 | 1 | | 2 | Zwei-Punkte-Vorsprung | 1 | 1 | 1 | | 3 | Treffpunkt | 1 | 1 | 1 | | 4 | Pankten | 1 | 0 | 0 | | 5 | Zwei-Pankte-Vorsprung | 1 | 0 | 0 | | 6 | Treffpankt | 1 | 0 | 0 | +----+-----------------------+------------+-------------+-----------+ 6 rows in set (0.01 sec) mysql>
所有的 PunktMatch 值都應該是 3 個 1 和 3 個 0。
現在看我正常查詢它們
mysql> SELECT `meldungstext` FROM `artikel` -> WHERE MATCH (`meldungstext`) AGAINST ('*punkt*' IN BOOLEAN MODE); +-----------------------+ | meldungstext | +-----------------------+ | Zwei-Punkte-Vorsprung | | Punkten | +-----------------------+ 2 rows in set (0.01 sec) mysql> SELECT `meldungstext` FROM `artikel` -> WHERE LOCATE('punkt',meldungstext)>0; +-----------------------+ | meldungstext | +-----------------------+ | Punkten | | Zwei-Punkte-Vorsprung | | Treffpunkt | +-----------------------+ 3 rows in set (0.00 sec) mysql> SELECT `meldungstext` FROM `artikel` -> WHERE `meldungstext` LIKE '%punk%'; +-----------------------+ | meldungstext | +-----------------------+ | Punkten | | Zwei-Punkte-Vorsprung | | Treffpunkt | +-----------------------+ 3 rows in set (0.00 sec) mysql>
OK 使用 MATCH .. AGAINST 與 punkt 不起作用。潘克特呢???
mysql> SELECT `meldungstext` FROM `artikel` WHERE `meldungstext` LIKE '%pankt%'; +-----------------------+ | meldungstext | +-----------------------+ | Pankten | | Zwei-Pankte-Vorsprung | | Treffpankt | +-----------------------+ 3 rows in set (0.00 sec) mysql>
GROUP BY
讓我們對 pankt執行我的大查詢mysql> SELECT id,meldungstext, -> COUNT(IF(MATCH (`meldungstext`) AGAINST ('*pankt*' IN BOOLEAN MODE),1,0)) PanktMatch, -> IF(LOCATE('pankt',meldungstext)>0,1,0) PanktLocate, -> meldungstext LIKE '%pankt%' PanktLike -> FROM `artikel` GROUP BY id,meldungstext; +----+-----------------------+------------+-------------+-----------+ | id | meldungstext | PanktMatch | PanktLocate | PanktLike | +----+-----------------------+------------+-------------+-----------+ | 1 | Punkten | 1 | 0 | 0 | | 2 | Zwei-Punkte-Vorsprung | 1 | 0 | 0 | | 3 | Treffpunkt | 1 | 0 | 0 | | 4 | Pankten | 1 | 1 | 1 | | 5 | Zwei-Pankte-Vorsprung | 1 | 1 | 1 | | 6 | Treffpankt | 1 | 1 | 1 | +----+-----------------------+------------+-------------+-----------+ 6 rows in set (0.01 sec) mysql>
這也是錯誤的,因為我應該看到 PanktMatch 的 3 個 0 和 3 個 1。
我嘗試了別的東西
mysql> SELECT id,meldungstext, MATCH (`meldungstext`) AGAINST ('+*pankt*' IN BOOLEAN MODE) PanktMatch, IF(LOCATE('pankt',meldungstext)>0,1,0) PanktLocate, meldungstext LIKE '%pankt%' PanktLike FROM `artikel` GROUP BY id,meldungstext; +----+-----------------------+------------+-------------+-----------+ | id | meldungstext | PanktMatch | PanktLocate | PanktLike | +----+-----------------------+------------+-------------+-----------+ | 1 | Punkten | 0 | 0 | 0 | | 2 | Zwei-Punkte-Vorsprung | 0 | 0 | 0 | | 3 | Treffpunkt | 0 | 0 | 0 | | 4 | Pankten | 1 | 1 | 1 | | 5 | Zwei-Pankte-Vorsprung | 1 | 1 | 1 | | 6 | Treffpankt | 0 | 1 | 1 | +----+-----------------------+------------+-------------+-----------+ 6 rows in set (0.00 sec) mysql>
我在 pankt 上加了一個加號,得到了不同的結果。什麼 2 而不是 3 ???
根據MySQL 文件,請注意它對萬用字元的說明:
星號用作截斷(或萬用字元)運算符。與其他運算符不同,它應該附加到要受影響的單詞上。如果單詞以 * 運算符之前的單詞開頭,則單詞匹配。
如果使用截斷運算符指定單詞,則不會從布爾查詢中刪除它,即使它太短(由 ft_min_word_len 設置確定)或停用詞。出現這種情況是因為單詞不是太短或停用詞,而是作為前綴,必須以以前綴開頭的單詞的形式出現在文件中。假設 ft_min_word_len=4。然後搜尋 ‘+word +the*’ 可能會返回比搜尋 ‘+word +the’ 更少的行數:
前一個查詢保持原樣,並且要求文件中同時出現單詞和 the*(以 the 開頭的單詞)。
後一個查詢被轉換為 +word(只需要 word 存在)。the 太短又是一個停用詞,任何一個條件都足以導致它被忽略。
基於此,萬用字元適用於令牌的背面,而不適用於正面。鑑於此,輸出必須是正確的,因為 3 個 punkt 的起始標記中有 2 個。與 pankt 相同的故事。這至少解釋了為什麼 3 行中有 2 行以及為什麼行數更少。