如何为tsquery
设置权重?我需要为从tsquery
获得的plainto_tsquery
设置权重。
有可能吗?像setweight(plainto_tsquery(''), 'A')
这样的东西,但它仅适用于tsvector
。
答案 0 :(得分:1)
我也有这个问题。我的用例是大型文档,很多部分,我希望提供一个选项,仅用于搜索标题文本"。 (标题有重量A并散布在整个文件中;其他部分的重量B,C或D取决于它们出现的位置。)
以下是两个应该有用的解决方案。
该函数将tsquery转换为文本,应用正则表达式设置权重,然后转换回tsquery。
CREATE FUNCTION setweight(query tsquery, weights text) RETURNS tsquery AS $$
SELECT regexp_replace(
query::text,
'(?<=[^ !])'':?(\*?)A?B?C?D?', ''':\1'||weights,
'g'
)::tsquery;
$$ LANGUAGE SQL IMMUTABLE;
示例:
select setweight( plainto_tsquery('fat cats and rats'), 'A' );
-- 'fat':A & 'cat':A & 'rat':A
select setweight( phraseto_tsquery('fat cats and rats'), 'A' );
-- 'fat':A <-> 'cat':A <2> 'rat':A
select setweight( to_tsquery('fat & (cat:A & rat) & !dog:*CD'), 'BC' );
-- 'fat':BC & 'cat':BC & 'rat':BC & !'dog':*BC
首先在您要搜索的全文列上创建其他索引。
e.g。
CREATE INDEX fulltext_idx
ON your_table USING gin
(fulltext)
CREATE INDEX fulltext_idx_A
ON your_table USING gin
(ts_filter(fulltext, '{a}'))
CREATE INDEX fulltext_idx_AB
ON your_table USING gin
(ts_filter(fulltext, '{a,b}'))
无论你需要什么重量组合。
然后,在搜索时,使用过滤的表达式。 e.g:
SELECT *
FROM your_table
WHERE ts_filter(fulltext, '{a}') @@ plainto_tsquery('your query')
搜索应在索引表达式上进行。
解决方案1为您提供了您正在寻找的功能,但加权查询的问题在于虽然postgres将使用索引来查找候选匹配,但仍需要拉回每个文档以检查权重。 / p>
就我而言,仅按标题搜索时,解决方案2似乎可以提供更好的性能。标题中的文本(权重A)使用比整个文档小得多的词汇表,因此fulltext_idx_A比fulltext_idx小得多,并且匹配后不需要重新检查结果。
对于您自己的情况,性能将完全取决于您自己的文档结构和查询的性质,因此请使用“解析分析”进行测试。选择更好的解决方案。考虑到票证的年龄,我想你已经解决了这个问题: - )
注意:ts_filter()和phraseto_tsquery()来自Postgres 9.6。
答案 1 :(得分:0)
这是有关Postgres全文搜索的最佳文章:
https://www.compose.com/articles/mastering-postgresql-tools-full-text-search-and-phrase-search/
,您还可以使用设置重量:
setweight(to_tsvector(coalesce($columnName, '')), '$weight')
列名类似users.name
(table.column)
以及您想要的重量,例如A,B或C