我目前正在调整我的文字搜索查询,以便为给定的搜索字词获得最佳结果。我正在寻找的是一种排名功能,它只会为搜索字段中的新唯一值提升分数。它也应该比仅仅前缀命中更好地得分。我能够通过庞大的查询获得所需的结果,但是想知道你是否可以使用秩函数实现更优雅的类似结果。我给你举个例子:
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
令人遗憾的是,它没有提供我想要的订单,因为它比完全独特的点击更能获得多次相同的点击。是否可以编写这样的自定义排名函数?
答案 0 :(得分:0)
我不太确定我是否理解你的问题,
您可以使用一些基本的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;
您仍然需要针对每个新搜索字词调整此查询,但现在看起来更容易了。