her*_*ver 3 postgresql full-text-search
如何设置权重tsquery?我需要为tsquery从plainto_tsquery.
是否可以?类似的东西setweight(plainto_tsquery(''), 'A'),但它仅适用于tsvector.
小智 5
我也有这个问题。我的用例是大文档,很多部分,我希望提供一个“仅搜索标题文本”的选项。(标题的权重为 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;
Run Code Online (Sandbox Code Playgroud)
例子:
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
Run Code Online (Sandbox Code Playgroud)
首先在要搜索的全文列上创建其他索引。
例如
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}'))
Run Code Online (Sandbox Code Playgroud)
对于您需要的任何重量组合。
然后,在搜索时,使用过滤后的表达式。例如:
SELECT *
FROM your_table
WHERE ts_filter(fulltext, '{a}') @@ plainto_tsquery('your query')
Run Code Online (Sandbox Code Playgroud)
搜索应该在索引表达式上进行。
解决方案 1 为您提供了您正在寻找的函数,但加权查询的问题在于,尽管 postgres 将使用索引来查找候选匹配项,但它仍然需要拉回每个文档以检查权重。
就我而言,仅按标题搜索时,解决方案 2 似乎提供了更好的性能。标题中的文本(权重A)使用的词汇量比整个文档中的要小得多,因此fulltext_idx_A比fulltext_idx小得多,匹配后不需要重新检查结果。
对于您自己的情况,性能将完全取决于您自己的文档结构和查询的性质,因此请使用“解释分析”进行测试以选择更好的解决方案。考虑到票的年龄,我想你已经解决了这个问题:-)
注意:ts_filter()和phraseto_tsquery()来自 Postgres 9.6。
| 归档时间: |
|
| 查看次数: |
4488 次 |
| 最近记录: |