Соответствует пункту «Считать и упорядочить» - PullRequest
2 голосов
/ 16 декабря 2011

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

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 ]

3 голосов
/ 16 декабря 2011

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

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;

Это даже позволит вам «оценить» важность каждого критерия выбора, предполагая, что пользователь (или алгоритм) может назначить взвешивание каждомуterm.

Одно предупреждение: если ваш запрос создается динамически, знаете ли вы о риске вставки SQL атак ?

2 голосов
/ 16 декабря 2011

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

CREATE OR REPLACE FUNCTION CountInString(text,text)
RETURNS integer AS $$
 SELECT(Length($1) - Length(REPLACE($1, $2, ''))) / Length($2) ;
$$ LANGUAGE SQL IMMUTABLE;

И использовать ее в select: select CountInString("Question",' what ') from "faq".

...