我目前正在调整我的文本搜索查询以获得给定搜索词的最佳结果。我正在寻找的是一个排名功能,它只会提高搜索字段中新的唯一值的分数。它还应该比前缀命中更好地对精确命中进行评分。我能够通过庞大的查询获得所需的结果,但想知道您是否可以使用排名函数更优雅地获得类似的结果。我给你举个例子:
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');
这是我使用搜索词“Kate”+“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
遗憾的是,这并没有提供我想要的顺序,因为它对多个相同的匹配项的评分要高于精确的独特匹配项。是否可以编写这样的自定义排名函数?
最佳答案
我不太确定我是否理解你的问题,
您可以通过以下方式使用一些基本的 SQL 关键字和聚合函数来简化您的查询:
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;
您仍然需要为每个新的搜索词调整此查询,但现在看起来稍微容易一些。
关于sql - 在 PostgreSQL 中对多个唯一值进行排名的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41185157/