FULLTEXT — Блог Валерия Леонтьева https://valera.ws Место публикации личных заметок. Технологии, управление, бизнес, жизнь Mon, 24 Nov 2008 08:32:55 +0000 ru-RU hourly 1 https://wordpress.org/?v=5.6.2 https://valera.ws/wp-content/uploads/2020/02/favicon.png FULLTEXT — Блог Валерия Леонтьева https://valera.ws 32 32 Поиск в MySQL. Часть 3 «FULLTEXT IN BOOLEAN MODE» https://valera.ws/2008.04.15~fulltext-in-mysql/ https://valera.ws/2008.04.15~fulltext-in-mysql/#comments Tue, 15 Apr 2008 14:53:10 +0000 http://valera.ws/2008.04.15~fulltext-in-mysql/ Читать далее Поиск в MySQL. Часть 3 «FULLTEXT IN BOOLEAN MODE» ]]> Поиск с учетом русской морфологии

Поиск в MySQL. Часть 3 «FULLTEXT IN BOOLEAN MODE»

В первой части рассказа о поиске в MySQL рассказывается про использование полнотекстного индекса FULLTEXT. При поиске неких ключевых слов в большом массиве текста, хранящегося в БД, без использования индекса не обойтись. Однако родные возможности полнотекстового поиска в СУБД MySQL не обеспечиват функционал для поиска с учетом русской морфологии. Решение этой проблемы описывалось во второй части «Поиск с учетом русской морфологии». И вот недавно в описанном алгоритме обнаружился большой недостаток. Что это за недостаток и как с ним бороться и описано в этой статье.

Для начала хочу заметить один нюанс. Не так давно вышел релиз СУБД PostgreSQL 8.3. И одной из важнейших его особенностей стало то, что полнотекстный поиск, причем еще и с поддержкой русской морфологии, включен в ядро СУБД. Теперь не надо использовать различные плагины и примочки, чтобы пользоваться возможностями полнотекстного о поиска. А возможности эти на порядок мощнее и щире возможностей fulltext-поиска в MySQL. По-этому, если поиск информации в базе для вашего проекта является одной из центральных «фишек», стоит смотреть в сторону Postgres.

Если же у вас нет выбора СУБД, или требования к поиску невысокие, можно пользоваться и моим решением на базе MySQL. Только необходимо учесть поправки для поискового запроса, описанные ниже.

По делу. При использовании конструкции MATCH … AGAINST СУБД ищет указанные в запросе ключевые слова в индексе, если подходящий найден, или в указанном поле данных. Поиск может проходить в трех разных режимах: в натуральном (обычном) и логическом (boolean mode). Общее между этими режимами то, что в обоих случаях фраза поиска, переданная в AGAINST будет разделена на слова. И при поиске будут находиться записи, в которых встречается хотя бы одно из указанных слов.

Например, при указании фразы «трудовой договор» будут найдены все строки, в которых встречается слово «трудовой» и все строки со словом «договор». На практике такой подход оказывается неприемлемым, так как выдает слишком много лишних результатов. Особенно ярко выражается проблема, когда одно слово очень популярное и находится в огромном количестве строк. В этом случае уточняющее слово практически не имеет смысла. И релевантность тут не спасет. Популярное слово может встретиться в строке 50 раз. В этом случае строка получит релевантность значительно выше, чем строка в которой оба слова встретились по одному разу.

В результате поиск по такому принципу в большом массиве информации становится неюзабельным. Обойти проблему можно с помощью второго режима поиска — поиска в логическом режиме. Его преимущество в том, что с помощью некоторых специальных операторов можно управлять значимостью и ролью слов в запросе, а также искать по фразам.

Для включения логического режима используется синтаксис: MATCH (…) AGAINST (‘…’ IN BOOLEAN MODE);

Оператор пишется в кавычках непосредственно перед ключевым словом, к которому он относится. Операторы, которые воспринимает анализатор запроса:

  • — (дефис, символизирующий «минус»). Этот оператор указывает, что данное ключевое слово не должно содержаться в поле (NOT);
  • + указывает, что слово должно обязательно содержаться в запросе (AND);
  • > и < соответственно увеличивают и уменьшают вес слова при подсчете релевантности;
  • ( и ) группируют слова для применения к ним оператора
  • ~ имеет смысл, схожий с «минусом», но оно слово не исключает, а просто уменьшает релевантность строки, в которой слово встретилось;
  • * — оператор усечения, ставится в конце слова и имеет классический смысл (например, слов*);
  • » (кавычка). В кавычки берутся фразы, по которым требуется искать целиком.

Следует обратить внимание так же на то, что результаты в случае использования логического режима автоматически не сортируются по релевантности.

Чтобы обеспечить точный поиск и релевантность вывода, передадим в запрос ключевые слова в обработанном виде. Первой частью пустим в кавычках фразу, составленную из слов, которые ввел пользователь (естественно, предварительно отфильтровав спец-символы). Установим перед ней оператор повышения релевантности «>». Далее через пробел открываем скобки. В них нужно указать слова, полученные от морфологического движка. Перед скобками ставим оператор уменьшения релевантности. Слова пишутся через пробел, а перед каждым словом ставится оператор «+».

Для наглядности приведем пример. При поиске по фразе «отпуск за работу» запрос будет выглядеть так: … MATCH (…) AGAINST (‘>»отпуск за работу» <(+отпуск +работу)’ IN BOOLEAN MODE) …

Кроме этого, из-за логического режима поиска необходимо вручную указать порядок вывода (сортировку) найденных строк. Для этого добавляем в выборку еще один столбец, который определяется так выражением MATCH … AGAINST с псевдонимом. Причем оно должно быть идентично выражению в блоке WHERE. Тогда СУБД будет выполнять поиск только один раз. Ну а в конец запроса нужно дописать, что сортировка идет по полю (через псевдоним) в порядке убывания.

Итак, теперь пример полного результирующего запроса. Поиск по фразе «отпуск за работу» в таблице table в полях text и text_index, по которым был предварительно создан полнотекстный индекс:

SELECT SQL_CALC_FOUND_ROWS *,
MATCH (text,text_index) AGAINST (‘>»отпуск за работу» <(+отпуск +работа)’ IN BOOLEAN MODE) AS rel
FROM table
WHERE MATCH (text,text_index) AGAINST (‘>»отпуск за работу» <(+отпуск +работа)’ IN BOOLEAN MODE)
ORDER BY rel DESC LIMIT 0, 10

Результаты такого поиска получается вполне неплохими и очень даже приемлемыми.

]]>
https://valera.ws/2008.04.15~fulltext-in-mysql/feed/ 14