Соответствует пункту "Считать и упорядочить"

Я пишу некоторые очень простые функции поиска для списка часто задаваемых вопросов. Я разделяю строку поиска по различным символам, включая пробелы. Затем выполнить выборку по линии

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".

Другие вопросы по тегам