全部产品
Search
文档中心

云原生数据库 PolarDB:使用中文分词

更新时间:Jan 05, 2026

本文将详细介绍如何在PolarDB PostgreSQL版(兼容Oracle)中,利用zhparser扩展来解决 PostgreSQL 内置全文检索功能无法有效处理中文的难题。通过集成此扩展,您可以轻松实现高效、精准的中文全文检索。

启用中文分词

  • 启用扩展。

    CREATE EXTENSION IF NOT EXISTS zhparser;
  • 创建中文分词配置。

    -- 创建一个名为 zh_cfg 的配置,并指定解析器为 zhparser
    CREATE TEXT SEARCH CONFIGURATION zh_cfg (PARSER = zhparser);
    
    -- 为特定类型的词元(如名词n, 动词v, 形容词a等)添加映射
    -- 这里使用 'simple' 字典,它会进行小写转换并检查停用词
    ALTER TEXT SEARCH CONFIGURATION zh_cfg ADD MAPPING FOR n,v,a,i,e,l WITH simple;
  • 设定全局参数。

    zhparser 提供了一些可调整的参数,您可以通过 ALTER ROLE 或 ALTER DATABASE 进行设置。

    -- 示例:开启“多元短语”模式,会尝试组合相邻的单字以形成更长的词
    ALTER ROLE ALL SET zhparser.multi_short = ON;
  • 测试分词效果。

    -- 1. 测试基本的词法分析 (ts_parse)
    SELECT * FROM ts_parse('zhparser', '2011年,保障房进入了更大规模的建设阶段。');
    
    -- 2. 测试将文本转换为词向量 (to_tsvector)
    --    这里使用我们刚刚创建的配置 'zh_cfg'
    SELECT to_tsvector('zh_cfg', '与2011年相比,2012年的保障房建设在资金配套上的压力将更为严峻。');
    
    -- 3. 测试将查询字符串转换为查询树 (to_tsquery)
    --    '保障房' 和 '资金' 和 '压力'
    SELECT to_tsquery('zh_cfg', '保障房 & 资金 & 压力');
    

创建并使用全文索引

  1. 准备示例表和数据:

    -- 创建一个示例表 t1
    CREATE TABLE t1 (
        id SERIAL PRIMARY KEY,
        name TEXT
    );
    
    -- 插入一些测试数据
    INSERT INTO t1 (name) VALUES
    ('中央加大保障房的建设和投入力度'),
    ('保障房资金配套压力严峻'),
    ('防火防盗是安全工作的重点');
  2. 为目标字段创建 GIN 索引:

    我们将为 t1 表的 name 字段创建一个基于 zh_cfg 配置的 GIN 索引。

    -- 使用我们创建的 'zh_cfg' 配置为 name 字段创建 GIN 索引
    CREATE INDEX idx_gin_t1_name ON t1 USING gin (to_tsvector('zh_cfg', name));
  3. 执行高效的全文检索查询:

    使用 @@ 操作符进行查询。关键在于 WHERE 子句中的 to_tsvector 表达式必须与 CREATE INDEX 中的表达式完全一致,这样才能确保优化器能够使用我们创建的索引。

    -- 示例1:查询包含“保障房”的记录
    -- 查询表达式 to_tsvector('zh_cfg', name) 与索引定义完全匹配,会高效利用索引
    SELECT name FROM t1 WHERE to_tsvector('zh_cfg', name) @@ to_tsquery('zh_cfg', '保障房');
    
    -- 示例2:查询同时包含“保障房”和“资金”的记录 (使用 & 操作符)
    SELECT name FROM t1 WHERE to_tsvector('zh_cfg', name) @@ to_tsquery('zh_cfg', '保障房 & 资金');
    
    -- 示例3:查询包含“防火”的记录
    SELECT name FROM t1 WHERE to_tsvector('zh_cfg', name) @@ to_tsquery('zh_cfg', '防火');