Соответствует пункту "Считать и упорядочить"
Я пишу некоторые очень простые функции поиска для списка часто задаваемых вопросов. Я разделяю строку поиска по различным символам, включая пробелы. Затем выполнить выборку по линии
SELECT *
FROM "faq"
WHERE
((LOWER("Question") LIKE '%what%'
OR LOWER("Question") LIKE '%is%'
OR LOWER("Question") LIKE '%a%'
OR LOWER("Question") LIKE '%duck%'))
Мне пришлось немного отредактировать это, поскольку оно генерируется нашим слоем доступа к данным, но оно должно дать вам представление о том, что происходит.
Проблема хорошо продемонстрирована с помощью вышеупомянутого запроса в том, что большинство вопросов, скорее всего, содержат слова a или есть в них, однако я не могу отфильтровать их, так как аббревиатуры могут быть важны для поисковика. Что было предложено, мы упорядочиваем по количеству подходящих ключевых слов. Однако я не смог найти способ сделать это в SQL (у нас нет времени на создание простой поисковой системы с индексом ключевых слов и т. Д.). Кто-нибудь знает, есть ли способ подсчета количества совпадений LIKE в операторе SQL и упорядочения по нему таким образом, чтобы вопросы с наибольшим количеством ключевых слов отображались в верхней части результатов?
2 ответа
Я предполагаю, что список подходящих ключевых слов вводится пользователем и динамически вставляется в запрос приложением непосредственно перед выполнением запроса. Если это так, я предлагаю изменить запрос следующим образом:
SELECT *
FROM "faq"
WHERE
((LOWER("Question") LIKE '%what%'
OR LOWER("Question") LIKE '%is%'
OR LOWER("Question") LIKE '%a%'
OR LOWER("Question") LIKE '%duck%'))
order by
case when LOWER("Question") LIKE '%what%' then 1 else 0 end +
case when LOWER("Question") LIKE '%is%' then 1 else 0 end +
case when LOWER("Question") LIKE '%a%' then 1 else 0 end +
case when LOWER("Question") LIKE '%duck%' then 1 else 0 end
descending;
Это даже позволит вам "взвешивать" важность каждого термина выбора, предполагая, что пользователь (или алгоритм) может назначить взвешивание каждому термину.
Одно предостережение: если ваш запрос создается динамически, знаете ли вы о риске атак на вставку SQL?
Вы можете написать функцию, которая подсчитывает вхождения одной строки в другую следующим образом:
CREATE OR REPLACE FUNCTION CountInString(text,text)
RETURNS integer AS $$
SELECT(Length($1) - Length(REPLACE($1, $2, ''))) / Length($2) ;
$$ LANGUAGE SQL IMMUTABLE;
И использовать его в выборе: select CountInString("Question",' what ') from "faq".