Fulltext Index в MySQL и встроенный поиск

Выбираете потолок - натяжные потолки россия. Круглосуточный ремонт для Вас. . Печать календарей и футболок: Печать карманных календарей. Изготовление по выгодным ценам.

С самой первой книжки по пхп, поиск по сайту у меня ассоциировался с конструкцией LIKE в MySQL. На не очень навороченных сайтах и на не очень навороченных поисках - она работала на ура, даже если полей, по которым шел поиск, было много. На маленьких сайтах вообще многое допустимо :) Однако, как только надо было сделать что-нить более или менее серьезное на этом фронте - как сразу LIKE шел в топку из-за своих тормозов. И не важно что это было - Sphinx, Lucene или написанный самим заказчиком типа мегаиндексатор (было однажды и такое) - возможности MySQL отметались  - и задача поиска переносилась на другие приложения. И только недавно я узнал, что оказывается MySQL сама отлично умеет все это делать!

Оказалось, что еще с версии 3.23.23 в MySQL была предусмотрена такая возможность - для этого нужно было создать Fulltext Index по нужным полям (на примере добавления в уже существующую таблицу):

ALTER TABLE news ADD FULLTEXT(headline, story);

И можно использовать для поиска конструкции вида:

SELECT headline, story FROM news WHERE MATCH (headline,story) AGAINST ('Hurricane');

как по идее ясно из кода - в AGAINST - слово, по которому ищем, в MATCH - поля по которым ищем :)

Мало того, что такой запрос выберет все что нужно, так записи еще и будут отсортированы по релевантности. Да-да, он и это умеет делать!

Но и это еще не все :) Поисковики, как правило, поддерживают свой мини-язык запросов. Тут это тоже есть:

SELECT headline, story FROM news WHERE MATCH (headline,story) AGAINST ('+Hurricane -Katrina' IN BOOLEAN MODE);

выберет все записи со словом "Hurricane", но не со словом "Katrina".

Не буду перепечатывать мануал - полнотекстовый поиск - это просто конфетка. Однако есть и определенные трудности:

  • По умолчанию короткие слова игнорируются. Короткие - это меньше 4 символов. Для этой настройки есть специальные переменные, однако если нет возможности их править на сервере заказчика - могут возникнуть проблемы;
  • Поиск по пустому значению не выдает все результаты (хотя спорно что такое поведение верное, но обычно именно так) - он же выдает ничего. Поэтому, вероятно для именно этой ситуации придется писать дополнительный запрос;
  • Опять же по умолчанию некоторые слова игнорируются (типа предлогов, артиклей и т.п. - к примеру, the, have, some) - настраивается, но если нет доступа - ну вы поняли :) ;
  • Если слово встречается более чем в 50% записей - то оно просто игнорируется. По идее - здраво, однако будет геморно объяснить тестеру почему такое творится, особенно на маленькой тестовой базе;
  • Вроде как не работает ток в MyISAM?
  • Слова ищутся целиком. Не как LIKE '%text%'.

В целом же - полнотекстовый поиск - клевая штука. Используя его - вовсе не нужно париться над встаиванием дополнительного чужеродного функционала в ваш проект, править чужие баги и мучаться с ручной (или по крону) переиндексацией базы. Да, со своими ньюансами, но в целом - тру. Советую :)

  • Lardok

    ALTER TABLE news ADD FULLTEXT(headline, story);

    …а вот с этим я что-то не понял: как именно записать в пхп-скрипте-то?

    с поиском понятно:
    $result = mysql_query(«SELECT * FROM news WHERE MATCH(name) AGAINST(‘слово’)», $db);

    …а для ALTER?

  • Vard

    $result = mysql_query(”ALTER TABLE имя_таблицы ADD FULLTEXT(список_полей_через_запятую)”, $db); и так для всех таблиц в которых нужно проиндексировать поля

  • Vijit

    Цитата: «Слова ищутся целиком. Не как LIKE ‘%text%’ »
    Можно искать по началу слова, используя оператором усечения *. Пример (из мануала):
    apple* найдет «apple», «apples», «applesauce», «applet» и т.д.

  • http://amdy.su AmdY

    К сожалению, оператор усечения можно использовать лишь в конце слова. Да и подглючивает это всё, лучше всё же сфинкс

  • Rina

    Огромное спасибо за статью )
    Я парился и не мог понять почему не находит строки , оказывается из за этого пункта:

    Если слово встречается более чем в 50% записей – то оно просто игнорируется. По идее – здраво, однако будет геморно объяснить тестеру почему такое творится, особенно на маленькой тестовой базе;


Информеры с тИЦ и PR: получить код для сайта