You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Postgres多语言全文搜索:如何让websearch_to_tsquery始终用OR?

解决PostgreSQL俄英混合全文搜索的OR逻辑匹配问题

问题背景

需要对包含俄语、英语及混合短语的字段执行全文搜索,用户查询词可能同时包含两种语言,要求所有查询词之间始终以OR逻辑匹配(即匹配任意一个词即可返回结果)。现有实现中,混合语言查询时俄语词被处理为AND连接,纯俄语查询时为OR连接,不符合预期。

现有索引与查询实现

索引构建代码

CREATE OR REPLACE FUNCTION make_tsvector (name text)
    RETURNS tsvector AS $$
BEGIN
    RETURN (setweight(to_tsvector('russian', name), 'A') || setweight(to_tsvector('english', name), 'B'));
END
$$ LANGUAGE 'plpgsql' IMMUTABLE;

CREATE INDEX projects_fts_name_idx ON projects USING gin (make_tsvector(name)); 

原查询代码

find = find.replace(' ', ' OR ');
result = await pool.query(`
                SELECT *,
                    ts_rank(make_tsvector(name), q_ru) AS r_ru,
                    ts_rank(make_tsvector(name), q_en) AS r_en
                FROM projects_v,
                    websearch_to_tsquery('russian', $1) AS q_ru,
                    websearch_to_tsquery('english', $1) AS q_en
                WHERE make_tsvector(name) @@ q_ru AND make_tsvector(name) @@ q_en
                ORDER BY r_ru DESC, r_en DESC
                LIMIT $2 OFFSET $3`,
                [ find, limit, offset ]);

问题根源

  1. WHERE条件逻辑错误:使用AND要求同时匹配俄语和英语查询结果,与OR逻辑需求相悖。
  2. websearch_to_tsquery行为限制:该函数依赖指定语言的分词器,处理混合语言时,非目标语言词会被忽略,剩余词的逻辑关系由websearch语法默认规则决定,导致混合查询时出现不符合预期的AND连接。

解决方案

1. 创建多语言TSQUERY生成函数

自定义函数将每个查询词同时用俄语、英语分词器处理,最终所有结果以OR逻辑连接:

CREATE OR REPLACE FUNCTION make_multi_lang_tsquery(query text)
RETURNS tsquery AS $$
DECLARE
    word_array text[];
    combined_tsquery tsquery := '';
    single_word text;
BEGIN
    word_array := string_to_array(trim(query), ' ');
    
    FOREACH single_word IN ARRAY word_array LOOP
        IF single_word <> '' THEN
            -- 每个词同时用两种分词器处理,结果用OR连接
            combined_tsquery := combined_tsquery || to_tsquery('russian', single_word) || to_tsquery('english', single_word);
        END IF;
    END LOOP;
    
    IF combined_tsquery = '' THEN
        RETURN to_tsquery('');
    END IF;
    
    RETURN combined_tsquery;
END
$$ LANGUAGE plpgsql IMMUTABLE;

2. 调整查询语句

使用自定义函数生成统一的查询条件,修正逻辑与排序规则:

// 无需替换空格为OR,直接传入原始查询字符串
result = await pool.query(`
    SELECT *,
        ts_rank(make_tsvector(name), multi_q) AS search_rank
    FROM projects_v,
        make_multi_lang_tsquery($1) AS multi_q
    WHERE make_tsvector(name) @@ multi_q
    ORDER BY search_rank DESC
    LIMIT $2 OFFSET $3`,
    [ find, limit, offset ]);

优化说明

  • 原索引可继续使用,自定义函数生成的TSQUERY能正确匹配俄英合并的TSVECTOR。
  • 无需额外语言识别,每个词同时用两种分词器处理,不识别的词会被自动忽略,兼顾两种语言的匹配需求。

内容的提问来源于stack exchange,提问作者Alexander Fedorov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 03:35:11