PostgreSQL如何合并多个tsvector并保留原始位置不添加偏移?
无位置偏移的tsvector合并方案
原生tsvector的
||运算符会自动将右侧向量的位置值加上左侧向量的最大位置值做偏移,无法满足保留原始位置、仅对相同位置去重的合并需求,可通过以下方案实现:
实现原理
PostgreSQL内置unnest()函数支持将tsvector拆解为词素(lexeme)、位置数组、权重数组的结构化结果集,我们只需将所有待合并的tsvector全部拆解,对相同词素的位置和权重组合做去重后,再重新聚合为tsvector即可。
自定义合并函数
你可以直接使用下面的SQL函数实现需求:
CREATE OR REPLACE FUNCTION tsvector_merge_no_offset(tsvector[]) RETURNS tsvector AS $$ SELECT array_to_tsvector(array_agg(DISTINCT lexeme || position_weight_str)) FROM ( SELECT lexeme, -- 拼接位置和权重标签,默认权重D无需显式标记 pos::text || CASE WHEN weight != 'D' THEN weight ELSE '' END AS position_weight_str FROM unnest($1) AS vec, unnest(vec) AS t(lexeme, positions, weights), unnest(positions, weights) AS pos_weight(pos, weight) ) AS tmp; $$ LANGUAGE sql IMMUTABLE PARALLEL SAFE;
使用示例
针对你给出的测试用例,调用方式如下:
SELECT tsvector_merge_no_offset(ARRAY['a:1 b:2'::tsvector, 'a:1 c:2 b:3'::tsvector]);
返回结果和你预期完全一致:'a':1 'b':2,3 'c':2
扩展说明
- 函数支持任意数量的tsvector合并,只需将所有待合并向量放入数组参数即可
- 相同词素的相同位置会自动去重,不会重复记录
- 权重标签会完整保留,如果不需要保留权重,删除拼接weight的逻辑即可
- 函数标记为
IMMUTABLE,支持在索引中使用
内容的提问来源于stack exchange,提问作者Kirill Salykin
相关产品推荐
相关产品推荐

