Postgresql:如何设置tsquery的权重

时间:2017-03-13 15:37:23

标签: postgresql full-text-search

如何为tsquery设置权重?我需要为从tsquery获得的plainto_tsquery设置权重。

有可能吗?像setweight(plainto_tsquery(''), 'A')这样的东西,但它仅适用于tsvector

2 个答案:

答案 0 :(得分:1)

我也有这个问题。我的用例是大型文档,很多部分,我希望提供一个选项,仅用于搜索标题文本"。 (标题有重量A并散布在整个文件中;其他部分的重量B,C或D取决于它们出现的位置。)

以下是两个应该有用的解决方案。

解决方案1:tsquery

的setweight函数

该函数将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

解决方案2:基于过滤后的tsvector的功能索引

首先在您要搜索的全文列上创建其他索引。

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