12.9.2 Поиски по полному тексту с использованием булевой логики
MySQL может выполнять поиски по полному тексту с использованием булевой логики с помощью модификатора IN BOOLEAN MODE. С этим модификатором определённые символы имеют специальное значение в начале или конце слов в строке поиска. В следующем запросе операторы + и - указывают, что слово должно быть присутствовать или отсутствовать соответственно для совпадения. Таким образом, запрос извлекает все строки, содержащие слово “MySQL”, но не содержащие слово “YourSQL”:
mysql> SELECT * FROM articles WHERE MATCH (title,body)
-> AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);
+----+-----------------------+-------------------------------------+
| id | title | body |
+----+-----------------------+-------------------------------------+
| 1 | MySQL Tutorial | DBMS stands for DataBase ... |
| 2 | How To Use MySQL Well | After you went through a ... |
| 3 | Optimizing MySQL | In this tutorial, we show ... |
| 4 | 1001 MySQL Tricks | 1. Never run mysqld as root. 2. ... |
| 6 | MySQL Security | When configured properly, MySQL ... |
+----+-----------------------+-------------------------------------+
При реализации этой функции MySQL использует то, что иногда называют неявной булевой логикой, в которой
+означаетAND-означаетNOT[нет оператора] подразумевает
OR
Поиски по полному тексту с использованием булевой логики обладают следующими характеристиками:
Они не сортируют строки автоматически по убыванию релевантности.
Таблицы
InnoDBтребуют индексFULLTEXTпо всем столбцам выраженияMATCH()для выполнения булевых запросов. Булевые запросы к индексу поискаMyISAMмогут работать даже без индексаFULLTEXT, хотя поиск в таком режиме будет довольно медленным.-
Минимальная и максимальная длина слова для параметров полного текста применяются к индексам
FULLTEXT, созданным с использованием встроенного парсераFULLTEXTи плагина парсера MeCab.innodb_ft_min_token_sizeиinnodb_ft_max_token_sizeиспользуются для индексов поискаInnoDB.ft_min_word_lenиft_max_word_lenиспользуются для индексов поискаMyISAM.Минимальная и максимальная длина слова для параметров полного текста не применяются к индексам
FULLTEXT, созданным с использованием парсера ngram. Размер токена ngram определяется параметромngram_token_size. Список стоп-слов применяется, управляемый
innodb_ft_enable_stopword,innodb_ft_server_stopword_tableиinnodb_ft_user_stopword_tableдля индексов поискаInnoDB, иft_stopword_fileдля индексовMyISAM.Поиск по полному тексту с использованием булевой логики не поддерживает использование нескольких операторов для одного слова, как в этом примере:
'++apple'. Использование нескольких операторов для одного слова приводит к ошибке синтаксиса в стандартный вывод. Поиск по полному тексту MyISAM успешно обрабатывает тот же запрос, игнорируя все операторы, кроме оператора, непосредственно прилегающего к слову поиска.Поиск по полному тексту MyISAM поддерживает только ведущие знаки плюс или минус. Например,
InnoDBподдерживает'+apple', но не поддерживает'apple+'. Указание знака плюс или минус в конце приводит к ошибке синтаксиса вInnoDB.Поиск по полному тексту InnoDB не поддерживает использование ведущего знака плюс со звездочкой (
'+*'), комбинации знаков плюс и минус ('+-') или комбинации знаков плюс и минус в начале ('+-apple'). Эти недопустимые запросы приводят к ошибке синтаксиса.Поиск по полному тексту InnoDB не поддерживает использование символа
@в булевых запросах. Символ@зарезервирован для использования оператора близости@distance.Они не используют порог в 50%, который применяется к индексам поиска
MyISAM.
Булевый поиск по полному тексту поддерживает следующие операторы:
-
+Ведущий или заключительный знак плюс указывает, что это слово должно присутствовать в каждой возвращаемой строке.
InnoDBподдерживает только ведущие знаки плюс. -
-Ведущий или заключительный знак минус указывает, что это слово не должно присутствовать ни в одной из возвращаемых строк.
InnoDBподдерживает только ведущие знаки минус.Примечание: Оператор
-действует только для исключения строк, которые иначе соответствуют другим поисковым терминам. Таким образом, булевый поиск, содержащий только термины, предваряемые-, возвращает пустой результат. Он не возвращает “все строки, кроме тех, которые содержат любой из исключаемых терминов”. -
(нет оператора)
По умолчанию (когда не указан ни
+, ни-), слово является необязательным, но строки, которые его содержат, оцениваются выше. Это имитирует поведение функцииMATCH() AGAINST()без модификатораIN BOOLEAN MODE. -
@distanceЭтот оператор работает только с таблицами
InnoDB. Он проверяет, начинают ли два или более слова в указанном расстоянии друг от друга, измеренном в словах. Укажите поисковые слова в строке с двойными кавычками непосредственно перед оператором@, например,distanceMATCH(col1) AGAINST('"word1 word2 word3" @8' IN BOOLEAN MODE) -
> <Эти два оператора используются для изменения вклада слова в значение релевантности, присваиваемое строке. Оператор
>увеличивает вклад, а оператор<уменьшает его. Смотрите пример после этого списка. -
( )Скобки группируют слова в подвыражения. Группы в скобках могут быть вложенными.
-
~Ведущая тильда действует как оператор отрицания, заставляя вклад слова в релевантность строки быть отрицательным. Это полезно для пометки “шумовых” слов. Строка, содержащая такое слово, оценивается ниже, чем другие, но не исключается полностью, как это происходит с оператором
-. -
*Звездочка служит оператором усечения (или подстановки). В отличие от других операторов, она присоединяется к слову, на которое влияет. Слова совпадают, если они начинаются со слова, предшествующего оператору
*.Если слово указано с оператором усечения, оно не удаляется из булевого запроса, даже если оно слишком короткое или является стоп-словом. Определяется ли слово как слишком короткое, зависит от значения параметра
innodb_ft_min_token_sizeдля таблицInnoDBилиft_min_word_lenдля таблицMyISAM. Эти параметры не применимы к индексамFULLTEXT, использующим парсер ngram.Усеченное слово рассматривается как префикс, который должен присутствовать в начале одного или нескольких слов. Если минимальная длина слова составляет 4, поиск
'+может вернуть меньше строк, чем поиск поword+the*''+, потому что второй запрос игнорирует слишком короткое слово поискаword+the'the. -
"Фраза, заключённая в двойные кавычки (
"), соответствует только строкам, которые содержат фразу буквально, так, как она была набрана. Двигатель полного текста разделяет фразу на слова и выполняет поиск в индексеFULLTEXTпо словам. Небуквенные символы не обязательно должны точно совпадать: для поиска по фразе требуется только точное соответствие словам фразы в том же порядке. Например,"test phrase"соответствует"test, phrase".Если фраза не содержит слов, которые есть в индексе, результат пустой. Слова могут отсутствовать в индексе по нескольким причинам: они могут отсутствовать в тексте, быть стоп-словами или быть короче минимальной длины индексированных слов.
Следующие примеры демонстрируют некоторые строки поиска, которые используют булевые операторы полного текста:
-
'apple banana'Найти строки, содержащие хотя бы одно из двух слов.
-
'+apple +juice'Найти строки, содержащие оба слова.
-
'+apple macintosh'Найти строки, содержащие слово “apple”, но при этом повышать рейтинг строк, если они также содержат “macintosh”.
-
'+apple -macintosh'Найти строки, содержащие слово “apple”, но не содержащие “macintosh”.
-
'+apple ~macintosh'Найти строки, содержащие слово “apple”, но если строка также содержит слово “macintosh”, понижать её рейтинг по сравнению со строками, не содержащими “macintosh”. Это более “мягкий” поиск, чем поиск
'+apple -macintosh', в котором наличие “macintosh” вообще исключает строку из результатов. -
'+apple +(>turnover <strudel)'Найти строки, содержащие слова “apple” и “turnover”, или “apple” и “strudel” (в любом порядке), но при этом повышать рейтинг “apple turnover” по сравнению с “apple strudel”.
-
'apple*'Найти строки, содержащие слова, такие как “apple”, “apples”, “applesauce” или “applet”.
-
'"some words"'Найти строки, содержащие точную фразу “some words” (например, строки, содержащие “some words of wisdom”, но не “some noise words”). Обратите внимание, что символы
", окружающие фразу, являются операторными символами, разделяющими фразу. Это не кавычки, которые окружают сам поисковый запрос.
Рейтинг релевантности для поиска InnoDB в булевом режиме
InnoDB полнотекстовый поиск моделируется на основе полнотекстового поискового движка Sphinx, и используемые алгоритмы основаны на алгоритмах ранжирования BM25 и TF-IDF. По этим причинам рейтинг релевантности для InnoDB булевого полнотекстового поиска может отличаться от рейтинга релевантности для MyISAM.
InnoDB использует вариацию системы взвешивания “частота термина - обратная частота документа” (TF-IDF), чтобы ранжировать релевантность документа заданному поисковому запросу. TF-IDF взвешивание основано на частоте появления слова в документе, с учетом частоты появления слова во всех документах коллекции. Другими словами, чем чаще слово встречается в документе и чем реже оно встречается во всей коллекции документов, тем выше рейтинг документа.
Как вычисляется рейтинг релевантности
Значение частоты термина (TF) — это количество раз, которое слово появляется в документе. Значение обратной частоты документа (IDF) для слова вычисляется по следующей формуле, где total_records — количество записей в коллекции, а matching_records — количество записей, в которых встречается поисковый термин.
${IDF} = log10( ${total_records} / ${matching_records} ) Когда в документе слово встречается несколько раз, значение IDF умножается на значение TF:
${TF} * ${IDF} Используя значения TF и IDF, рейтинг релевантности документа рассчитывается по этой формуле:
${rank} = ${TF} * ${IDF} * ${IDF}Эта формула продемонстрирована в следующих примерах.
Рейтинг релевантности для поиска по одному слову
Этот пример демонстрирует вычисление рейтинга релевантности для поиска по одному слову.
mysql> CREATE TABLE articles (
-> id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
-> title VARCHAR(200),
-> body TEXT,
-> FULLTEXT (title,body)
->) ENGINE=InnoDB;
Query OK, 0 rows affected (1.04 sec)
mysql> INSERT INTO articles (title,body) VALUES
-> ('MySQL Tutorial','This database tutorial ...'),
-> ("How To Use MySQL",'After you went through a ...'),
-> ('Optimizing Your Database','In this database tutorial ...'),
-> ('MySQL vs. YourSQL','When comparing databases ...'),
-> ('MySQL Security','When configured properly, MySQL ...'),
-> ('Database, Database, Database','database database database'),
-> ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
-> ('MySQL Full-Text Indexes', 'MySQL fulltext indexes use a ..');
Query OK, 8 rows affected (0.06 sec)
Records: 8 Duplicates: 0 Warnings: 0
mysql> SELECT id, title, body,
-> MATCH (title,body) AGAINST ('database' IN BOOLEAN MODE) AS score
-> FROM articles ORDER BY score DESC;
+----+------------------------------+-------------------------------------+---------------------+
| id | title | body | score |
+----+------------------------------+-------------------------------------+---------------------+
| 6 | Database, Database, Database | database database database | 1.0886961221694946 |
| 3 | Optimizing Your Database | In this database tutorial ... | 0.36289870738983154 |
| 1 | MySQL Tutorial | This database tutorial ... | 0.18144935369491577 |
| 2 | How To Use MySQL | After you went through a ... | 0 |
| 4 | MySQL vs. YourSQL | When comparing databases ... | 0 |
| 5 | MySQL Security | When configured properly, MySQL ... | 0 |
| 7 | 1001 MySQL Tricks | 1. Never run mysqld as root. 2. ... | 0 |
| 8 | MySQL Full-Text Indexes | MySQL fulltext indexes use a .. | 0 |
+----+------------------------------+-------------------------------------+---------------------+
8 rows in set (0.00 sec) Всего 8 записей, из которых 3 соответствуют поисковому термину “database”. Первая запись (id 6) содержит поисковый термин 6 раз и имеет рейтинг релевантности 1.0886961221694946. Это значение вычислено с помощью значения TF 6 (поисковый термин “database” встречается 6 раз в записи id 6) и значения IDF 0.42596873216370745, которое вычисляется следующим образом (где 8 — общее количество записей, а 3 — количество записей, в которых встречается поисковый термин):
${IDF} = LOG10( 8 / 3 ) = 0.42596873216370745 Затем значения TF и IDF подставляются в формулу ранжирования:
${rank} = ${TF} * ${IDF} * ${IDF}Выполнение вычисления в командной строке MySQL возвращает значение рейтинга 1.088696164686938.
mysql> SELECT 6*LOG10(8/3)*LOG10(8/3);
+-------------------------+
| 6*LOG10(8/3)*LOG10(8/3) |
+-------------------------+
| 1.088696164686938 |
+-------------------------+
1 row in set (0.00 sec) Вы можете заметить небольшую разницу в значениях рейтинга, возвращаемых оператором SELECT ... MATCH ...
AGAINST и командной строкой MySQL (1.0886961221694946 против 1.088696164686938). Разница обусловлена тем, как происходит приведение типов между целыми числами и числами с плавающей точкой/двойной точностью внутри InnoDB (включая связанные вопросы точности и округления), и как это делается в других местах, например, в командной строке MySQL или других типах калькуляторов.
Рейтинг релевантности для поиска по нескольким словам
Этот пример демонстрирует вычисление рейтинга релевантности для полнотекстового поиска по нескольким словам, основанного на таблице articles и данных, использованных в предыдущем примере.
Если вы ищете по нескольким словам, значение рейтинга релевантности является суммой значений рейтинга релевантности для каждого слова, как показано в этой формуле:
${rank} = ${TF} * ${IDF} * ${IDF} + ${TF} * ${IDF} * ${IDF}Выполнение поиска по двум терминам ('mysql tutorial') возвращает следующие результаты:
mysql> SELECT id, title, body, MATCH (title,body)
-> AGAINST ('mysql tutorial' IN BOOLEAN MODE) AS score
-> FROM articles ORDER BY score DESC;
+----+------------------------------+-------------------------------------+----------------------+
| id | title | body | score |
+----+------------------------------+-------------------------------------+----------------------+
| 1 | MySQL Tutorial | This database tutorial ... | 0.7405621409416199 |
| 3 | Optimizing Your Database | In this database tutorial ... | 0.3624762296676636 |
| 5 | MySQL Security | When configured properly, MySQL ... | 0.031219376251101494 |
| 8 | MySQL Full-Text Indexes | MySQL fulltext indexes use a .. | 0.031219376251101494 |
| 2 | How To Use MySQL | After you went through a ... | 0.015609688125550747 |
| 4 | MySQL vs. YourSQL | When comparing databases ... | 0.015609688125550747 |
| 7 | 1001 MySQL Tricks | 1. Never run mysqld as root. 2. ... | 0.015609688125550747 |
| 6 | Database, Database, Database | database database database | 0 |
+----+------------------------------+-------------------------------------+----------------------+
8 rows in set (0.00 sec) В первой записи (id 8) 'mysql' встречается один раз, а 'tutorial' — дважды. Для 'mysql' есть шесть совпадающих записей, а для 'tutorial' — две. Командная строка MySQL возвращает ожидаемое значение рейтинга, подставив эти значения в формулу ранжирования для поиска по нескольким словам:
mysql> SELECT (1*log10(8/6)*log10(8/6)) + (2*log10(8/2)*log10(8/2));
+-------------------------------------------------------+
| (1*log10(8/6)*log10(8/6)) + (2*log10(8/2)*log10(8/2)) |
+-------------------------------------------------------+
| 0.7405621541938003 |
+-------------------------------------------------------+
1 row in set (0.00 sec) Небольшая разница в значениях рейтинга, возвращаемых оператором SELECT ... MATCH ... AGAINST и командной строкой MySQL, объясняется в предыдущем примере.
© 2025 Oracle
Licensed under the GPLv2 License.