Полнотекстовый поиск mySQL по 3 символам. Решено.

Предисловие

mySQLВ данной статье я решил изложить логическое и лёгкое решение проблемы 3-х символьного полнотекстового поиска в БД посредствами php и mySQL. Решение могут применить те пострадавшие, чей хостер по запросу клиента не хочет или не может изменить в настройках sql сервера параметр ft_min_word_len. Материал предполагает минимальные, поверхностные знание PHP и языка запросов SQL.

Создавая движок для своего информационного ресурса notavkusa.ru Я, как и многие, столкнулся с интересной проблемой. Мне было просто крайне необходимо реализовать релевантный поиск рецептов по ингредиентам. Многие ингредиенты состояли из трех символов, например сыр, лук, мед и т.д. Написав несколько незамысловатых строчек кода, я вдруг обнаружил что поиск по трех-символьным словам просто не производится. И тогда я вспомнил о том, что по умолчанию в настройках mySQL всегда и везде установлен параметр ft_min_word_len = 4, просто выкидывающий слова менее четырех символов из поисковой строки SQL запроса.

Сделано это с целью того, чтобы снизить нагрузку на сервак при поиске и отсечь лишние слова, содержащие менее четырех символов. Например такие как and, or, for, a, the и т.д. И, к сожалению, нашим отечественным хостинг компаниям глубоко наплевать на наш родной русский язык. NotaVkusa.ru в момент написания статьи хостится на Jino. На запрос в техподдержку о перенастройке сервера мне ответили примерно следующее: мы бы рады вам помочь, но на данном сервере хостится ещё 50 ресурсов, которым эта функция нахрен не сдалась. Я попросил перевестись на ви-ай-пи аккаунт где хостится не более 5 ресурсов, на что получил отказ и ответ, что единственная возможность настроить у них mySQL под себя — арендовать выделенный сервак.

Увы, проект не приносит столько бабла, и окупиться выделка просто не может. Как мы знаем из документации mySQL, этот параметр не может быть изменен динамически. Я облазил весь интернет, тысячи форумов, но адекватного решения ни у кого не было. Были предложения выгружать всю БД в массив, организовывать релевантный поиск посредством чистого php, но мне страшно представить сколько для этого понадобится ресурсов, особенно когда сайт разрастется до миллиона страниц. Пришлось думать самому, и решение, на самом деле, лежит на поверхности, и занимает пару строк кода.

Решение

Давайте представим, что в нашем великом и могучем языке все 3-х буквенные слова вдруг резко превратились в эти буквенные =) Ага, вот и оно. Логический алгоритм очень прост, все слова из трех букв, и даже самое знаменитое слово, мы будем хранить в бд в 6 буквах, просто повторяя их дважды!

  • Сыр = СырСыр
  • дух = духдух
  • х…й = х…йх…й

Да, сейчас вы закричите, я не буду переписывать 5 000 текстов каждый из 10 000 знаков под такую белеберду, да и пользователь никогда не введет в поиске «Как приготовить супсуп». Конечно нет, и я кину спойлер на перёд — не придется.

Базу придется преобразовать один раз с помощью регулярки, а затем мы напишем 2 функции, которые будем вызывать для обработки любых текстовых запросов. Одну для вводимых(входящих) данных форм, другую для выводимых из БД(исходящих). Функции состоят из одной короткой регулярки. Т.е.:

  • одна регулярка преобразовывает в тексте «Жил был дух» в «ЖилЖил былбыл духдух» не трогая слова состоящие из большего и меньшего кол-ва символов.
  • другая для вывода данных, ищет в тексте дебиловатые 6ти-буквенные слова в которых первые три символа и последние три — повторяются.

function DuhDuh($string) { //фигачим во входной строке все 3-х буквенное в 6 символов и возвращаем
$string = preg_replace("/\b([А-ЯЁ]{3})\b/siu","\\1\\1",$string); //сыр = сырсыр
return $string;
}

function Duh($string) { //фигачим дебиловатые слова вроде сырсыр обратно в нормальные
$string = preg_replace('/\b([А-ЯЁ]{3})\\1\b/siu', '\\1', $inString); //сырсыр = сыр
return $string;
}

Теперь на входе в БД (любые формы, реги и т.д.) мы проводим через функцию DuhDuh, а любые выходные данные наоборот через Duh.

Помощью незамысловатого цикла прогоняем нашу базу через функцию DuhDuh чтобы все неприличные слова стали шести-буквенными и сохранились в базе по-новому.

Получается следующий алгоритм действий.

  1. Пользователь вводит в поисковую строку «Что такое сыр»
  2. Функция DuhDuh преобразует её в «ЧтоЧто такое сырсыр»
  3. Эта строка отправляется в БД в полнотекстовый поиск, и возвращает абсолютно нормальный результат, в виде «чточто такое сырсыр. Сырсыр этоэто молочный продукт…»
  4. Прогоняем выходной результат через функцию Duh, и имеем следующий стринг: Сыр это молочный продукт.
  5. Радуемся решению, на радостях идем пить зеленый чайчай или кофе.

А теперь для тех, кто не дружит с регулярными выражениями, что же там написано на примере первой функции. Для второй — тренеруйте мозг сами =)

Преобразователь трехсимвольный слов для полнотекстового поиска

Добавить комментарий для REMONTKt Отменить ответ

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>