FULLTEXT поиск и короткие слова

Задача
FULLTEXT поиск по коротким словам не возвращает записей.

Решение
Измените значение параметра минимальной длины слова для механизма индексирования.

Обсуждение
В тексте, подобном KJV, некоторые слова имеют особое значение, например «Бог» или «грех». Но если вы, работая с сервером MySQL 3.23, выполните FULLTEXT поиск этих слов в таблице kjv, то обнаружите любопытный результат – ни того, ни другого слова как будто никогда и не было в тексте:

mysql> SELECT COUNT(*) FROM kjv WHERE MATCH(vtext) AGAINST('God');

+------------ +
| COUNT(*) |
+ ------------+
| 0 |
+ ------------+

mysql> SELECT COUNT(*) FROM kjv WHERE MATCH(vtext) AGAINST('sin');

+ ------------+
| COUNT(*) |
+ ------------+
| 0 |
+ ------------+

Одно из свойств индексатора – игнорирование «слишком общих» слов (то есть слов, присутствующих более чем в половине записей). Так, из индекса удаляются слова типа «the» и «and», но в данном случае мы имеем дело с чемто иным.


Давайте сосчитаем общее количество записей и (при помощи шаблонов SQL) количество записей, содержащих каждое из слов:1

mysql> SELECT COUNT(*) AS 'total verses',
> COUNT(IF(vtext LIKE '%God%',1,NULL)) AS 'verses containing "God"',
> COUNT(IF(vtext LIKE '%sin%',1,NULL)) AS 'verses containing "sin"'
> FROM kjv;

+-------------- + -----------------------------+---------------------------- +
| total verses | verses containing "God" | verses containing "sin" |
+-------------- +----------------------------- + ----------------------------+
| 31102 | 4118 | 1292 |
+-------------- + -----------------------------+ ----------------------------+

Ни одно из слов не присутствует более чем в половине стихов, так что полно текстовый поиск не удался не изза частого употребления слов. Причина в том, что по умолчанию в индексы не включаются слова, длина которых меньше четырех символов.


Если вы работаете с сервером MySQL 3.23, то вам ничего не удастся с этим поделать (по крайней мере, ничего более простого, чем обращение к исходным текстам MySQL с их повторной компиляцией).

Но начиная с версии MySQL 4.0 минимальная длина слова является настраиваемым параметром, который можно изменить, задав переменную сервера ft_min_word_len. Например, чтобы включать в индекс слова, содержащие три и более символов, добавьте строку set variable в группу [mysqld] файла /etc/my.cnf (или другого файла, в котором вы храните настройки сервера):

[mysqld]
set variable = ft_min_word_len=3

Сохраните изменения, перезапустите сервер и пересоздайте индекс FULLTEXT, чтобы новое значение вступило в силу:

mysql> ALTER TABLE kjv DROP INDEX vtext;
mysql> ALTER TABLE kjv ADD FULLTEXT (vtext);

Давайте посмотрим, включает ли новый индекс короткие слова:

mysql> SELECT COUNT(*) FROM kjv WHERE MATCH(vtext) AGAINST('God');

+------------ +
| COUNT(*) |
+ ------------+
| 3878 |
+ ------------+

mysql> SELECT COUNT(*) FROM kjv WHERE MATCH(vtext) AGAINST('sin');

+ ------------+
| COUNT(*) |
+ ------------+
| 389 |
+ ------------+

Так то лучше!
Но почему запрос с MATCH() находит 3878 и 389 записей, в то время как при веденный ранее запрос с LIKE нашел 4118 и 1292 записей? Поиск по образцу с помощью LIKE ищет соответствующие подстроки, а поиск FULLTEXT, осуществляемый MATCH(), ищет только целые слова..



Оцените статью: (0 голосов)
0 5 0

Статьи из раздела MySQL на эту тему:
Буквальная интерпретация метасимволов в шаблонах
Включение и исключение слов из FULLTEXT - поиска
Поиск по образцу с помощью регулярных выражений
Поиск по образцу с помощью шаблонов SQL
Поиск с помощью индекса FULLTEXT

Вернуться в раздел: MySQL / 4. Работа со строками