ГДЕ x НРАВИТСЯ '% $ find%' - Что если $ find = 2 отдельных значения? - PullRequest
1 голос
/ 09 августа 2011

Я создаю функцию поиска для каталога товаров.

Вот код ввода:

<form name="search" method="post" action="'.$PHP_SELF.'">
    <div>
    Search for: <input type="text" name="find" />
    <input type="hidden" name="searching" value="yes" />
    <input type="submit" name="search" value="Search" />
    </div>
</form>

Вот запрос, который запрашивает у базы данных Mysql совпадение:

SELECT * FROM `products` WHERE upper(`desc`) LIKE'%$find%'

Все это прекрасно работает, когда пользователь ищет строку из одного слова.

Проблема здесь в том, что когда пользователь ищет строку из двух слов, совпадение не найдено, поскольку иногда эти строки относятся к отдельным функциям.

Примером этого может служить каталог продуктов, содержащий информацию о различных конфетах:

Вы получаете батончики с конфетами, коробки с конфетами, пакеты с конфетами и т.д ...

Теперь, хотя некоторые из описаний, содержащихся в поле desc, содержат слова «шоколад и батончик», некоторые содержат варианты, например «фирменные батончики по 120 г шоколада».

Это вызывает проблему в приведенном выше коде, потому что если пользователь ищет «плитку шоколада», если описание в поле desc явно не содержит эту вариацию, совпадения возвращаться не будут.

Я бы хотел, чтобы при поиске «плитки шоколада» возвращалось любое совпадение, содержащее варианты «шоколад» и «плитка».

Есть ли у кого-нибудь какие-либо сведения о том, как я буду выполнять эту задачу?

Возможно превратить $find в массив и сделать "" разделителем?

Ответы [ 5 ]

1 голос
/ 09 августа 2011

Вы должны изучить ПОЛНЫЙ ТЕКСТ ИНДЕКС Документация

desc LIKE '%word%' будет становиться все тяжелее и тяжелее.Пользователь также может предоставить 2 слова или даже больше.Просто разбейте запрос на несколько слов и создайте предложение where, охватывающее все возможности:

WHERE desc LIKE '%word1%' or desc LIKE '%word2%' OR  ....

Опять же, это не очень эффективно и не быстро, FULLTEXT + MATCH AGAINST работает лучше.

1 голос
/ 09 августа 2011

Может быть, вы могли бы сделать что-то вроде этого:

$keywords_array = explode(' ', $find);

$qry = "SELECT * FROM `products` WHERE `desc` LIKE '%" 
       . implode("%' OR `desc` LIKE '%", $keywords_array) 
       . "%'";

Вывод для $find = 'this':

SELECT * FROM products WHERE desc LIKE '% this%'

Вывод для $find = 'this and that':

ВЫБРАТЬ * ИЗ products ГДЕ desc НРАВИТСЯ'% this% 'ИЛИ desc НРАВИТСЯ'% и%'OR desc LIKE'% that% '

Это, безусловно, очень базовая функциональность, но вы поняли идею.

1 голос
/ 09 августа 2011

Вам нужно будет разбить строку на части и добавить их все в предложение where отдельно.то есть:

.... WHERE `desc` LIKE '%bar%' OR `desc` LIKE '%chocolate%'

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

Возможно, вы сможете быстрее получить результаты, используя FULLTEXT.Это требует дополнительной работы по настройке базы данных, но, что более важно, это, вероятно, не будет полезно в приведенном вами примере, поскольку FULLTEXT обычно отбрасывает короткие слова из индекса.Он настраивается, так что вы можете заставить его работать, но смысл FULLTEXT состоит в том, чтобы создать поисковый индекс для больших блоков текста;на самом деле он не предназначен для более коротких строк.

Более распространенными решениями для такого рода проблем являются использование тегов и поиск по тегам вместо строк.Это предполагает, в основном, наличие отдельной таблицы со всеми соответствующими ключевыми словами из каждой записи, которые хранятся отдельно.Это позволяет вам очень быстро искать, потому что вы можете полностью избавиться от подстановочных знаков.Вы даже можете добавить дополнительные ключевые слова-синонимы, которых может не быть в тексте, что может сделать поиск намного проще в использовании.

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

0 голосов
/ 09 августа 2011

Первая проблема - разделить поиск на отдельные слова. Это легко сделать в самом PHP, но, в зависимости от вашего поиска, вы также можете включить фразы, например, "this is a phrase" Если нет, то просто разделить текст поиска по пробелам.

Для вашей второй проблемы уже опубликованы оба возможных решения, либо вы можете использовать ... LIKE 'chocolate% OR LIKE 'bar% (примечание: я добавил% только после слова - я бы избегал использовать его с обеих сторон, за исключением того, что вы хотите найти wordparts а также, например, hocol должен по-прежнему соответствовать chocolade . Это очень медленно, так как индекс не может быть использован!

Лучшим решением, как уже упоминалось, будет полнотекстовый поиск с использованием MATCH()... AGAINST(), поскольку это решение использует полнотекстовые индексы и значительно ускоряет поиск!

0 голосов
/ 09 августа 2011

А как насчет перехода к регулярному выражению?

Вы можете заменить пробелы на | в $find (или любой другой синтаксис ввода, который вы предпочитаете) для имитации «ОК»:

"chocolate bar" => "chocolate | bar" (или даже "\ b (chocolate | bar) \ b" , если вам нужны границы слов)

или вы можете преобразоватьследовать имитации «И»

«шоколадка» => «шоколад. * плитка»

и затем выполнить:

WHERE desc REGEXP '$find'

Удвойте проверку, если с вами все в порядке.

...