Я взял три строки в вашем вопросе и добавил их в таблицу плюс еще три строки pankt
вместо punkt
.
Следующее было выполнено с использованием MySQL 5.5.12 для 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>
ОК, используя MATCH .. ПРОТИВ с punkt не работает. Что насчет pankt ???
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>
Это также неправильно, потому что я должен видеть 3 0 и 3 1 для PanktMatch.
Я пробовал что-то еще
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»:
Первый запрос остается без изменений и требует наличия в документе как слова, так и * (слова, начинающиеся с).
Последний запрос преобразуется в + word (требуется только слово). и слишком короткое, и стоп-слово, и любого условия достаточно, чтобы его игнорировать.
Исходя из этого, подстановочный знак применим для задней части токенов, а не для передней. В свете этого вывод должен быть правильным, потому что 2 из стартовых токенов 3-х пунктов. Та же самая история с pankt. Это как минимум объясняет, почему 2 из 3 и почему меньше строк.