2016-12-16 12 views
1

В настоящее время я настраиваю свои поисковые запросы, чтобы получить наилучшие результаты для заданных условий поиска. Я ищу функцию ранжирования, которая увеличит счет только для новых уникальных значений в искомом поле. Он также должен оценивать точные удары лучше, чем просто префиксные хиты. Я смог достичь желаемых результатов с помощью громоздкого запроса, но задавался вопросом, могли бы вы добиться более близких результатов, более элегантных, используя функцию ранжирования. Я дам вам пример:Функция для ранжирования нескольких уникальных значений в PostgreSQL

CREATE TABLE book (
    id BIGSERIAL NOT NULL PRIMARY KEY, 
    title VARCHAR(255) NOT NULL 
); 

INSERT INTO book (title) VALUES ('Kate Mat'); 
INSERT INTO book (title) VALUES ('Kate Kate Mate'); 
INSERT INTO book (title) VALUES ('Cat Mat'); 

Вот мой громоздкий запрос с «Кейт» поисковых терминов + «Mat»:

SELECT 
    title, 
    a1 + a2 + b1 + b2 AS score 
FROM (
     SELECT 
     title, 
     CASE WHEN to_tsvector('english', title) @@ to_tsquery('kate:*') 
      THEN 1 
     ELSE 0 
     END AS a1, 
     CASE WHEN to_tsvector('english', title) @@ to_tsquery('kate') 
      THEN 0.5 
     ELSE 0 
     END AS a2, 
     CASE WHEN to_tsvector('english', title) @@ to_tsquery('mat:*') 
      THEN 1 
     ELSE 0 
     END AS b1, 
     CASE WHEN to_tsvector('english', title) @@ to_tsquery('mat') 
      THEN 0.5 
     ELSE 0 
     END AS b2 
     FROM book 
    ) scoredProducts 
ORDER BY score DESC; 

#----------------------results------------------------- 
title   score 
Kate Mat  3  -- exact hit for both terms 
Kate Kate Mate 2.5  -- exact hit for 'Kate'. prefix hit for 'Mat' 
Cat Mat   1.5  -- exact hit for 'Mat' 

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

SELECT 
    title, 
    ts_rank(to_tsvector('english', book.title), to_tsquery('kate:* | mat:*')) AS score 
FROM book 
ORDER BY score DESC; 

#----------------------results------------------------- 
title   score 
Kate Kate Mate 0.0683918  -- prefix hits for both terms 
Kate Mat  0.06079271  -- exact hit gets scored less 
Cat Mat   0.030396355 

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

ответ

0

Я не совсем уверен, если я понимаю вашу проблему,
Вы можете упростить запрос, используя несколько основных ключевых слов SQL и агрегатный Funtion следующим образом:

SELECT 
    b.title, 
    sum(case when to_tsvector('english' , title) @@ to_tsquery(a.keyword) 
      then a.score end) AS score 
    FROM book b 
    cross join ( 
    values 
    ('kate:*', 1), 
    ('kate', 0.5), 
    ('mat:*', 1), 
    ('mat', 0.5) 
) as a(keyword, score) 
group by b.title 
ORDER BY score DESC; 

Вы все еще должны адаптировать этот запрос для каждого нового поискового термина, но теперь это кажется немного легче.

+0

Это более компактно, не знаю о значениях объединения. Моя цель состояла бы в том, чтобы иметь функцию, которая могла бы выполнять поисковые термины, такие как «kate mat ...», и просто вычисляет порядок с приоритетом уникальных и точных попаданий. – SlideM