全部产品
Search
文档中心

实时数仓Hologres:全文倒排索引

更新时间:Feb 13, 2026

Hologres自V4.0版本起支持全文倒排索引,该功能基于高性能全文检索引擎Tantivy构建,提供高性能检索能力,同时支持BM25相似性评分算法,提供文档排序、关键词检索、短语检索等多方面能力。

实现原理

将检索源文本写入Hologres后,Hologres会根据索引配置,对每个数据文件,构建全文倒排索引文件。该过程首先通过分词器对文本进行分词,得到若干分词token,然后通过索引记录每个token与检索源文本的映射关系、位置和词频等相关信息。

在对文本进行检索时,先对检索对象文本进行分词,得到对象token集合。通过BM25算法计算检索源的每个文本与检索对象token集合的相关性分数,实现高性能、高精度的全文检索。

注意事项

  • 仅支持Hologres V4.0及以上版本的列存表、行列共存表使用全文倒排索引功能,不支持行存表。

  • 仅支持对TEXT/CHAR/VARCHAR类型的列创建全文倒排索引。

  • 仅支持对单列构建全文倒排索引。每一列仅支持构建一个全文倒排索引。如果有多列需要构建,则需要创建多个索引。

  • 在创建全文倒排索引后,针对表中现有数据及后续批量写入的新数据,索引文件将随着数据的合并(Compaction)过程进行异步构建。在索引文件构建完成之前,数据的BM25相关性分数为0。

  • 针对创建全文倒排索引后的数据实时写入场景,在Hologres V4.0.8版本之前,索引会在数据实时写入时同步构建。从V4.0.8版本开始,为了保障数据实时写入的效率与索引构建的性能,系统将以1秒为间隔,定时异步刷新内存中的实时索引,只有在刷新后,才能通过索引查询到相关数据。

  • 全文检索仅支持在已创建全文索引的列上执行,不支持在未构建索引的情况下进行暴力计算。

  • 建议使用Serverless Computing资源执行数据的批量导入,Serverless资源将在数据导入时同步完成Compaction及全文索引构建,详情请参见使用Serverless Computing执行读写任务使用Serverless Computing执行Compaction任务。如不使用Serverless资源,建议在批量导入数据或修改索引后,手动执行如下命令触发Compaction

    VACUUM <schema_name>.<table_name>;
  • BM25检索算法计算的相关性分数为文件级别,如果您的数据导入量较小,建议按需手动触发Compaction,以完成文件合并,提升检索准确率。

  • 支持使用Serverless Computing资源执行全文检索的查询。

  • 推荐按下表场景选择合适的分词器:

    场景

    分词器

    备注

    长文章关键词提取

    Jieba

    支持新词发现、复杂模式切换。

    中文描述类文本检索

    IK

    精确识别中文术语。

    英文标题类文本检索

    Simple、Whitespace、Standard

    简单高效,根据目标英文文本按需使用。

    日志类文本模糊检索

    Ngram

    无需词典,满足文本的模糊查询需求。

    中文商品/人名拼音检索

    Pinyin

    中文全拼、首字母、多音字推导等丰富的中文拼音场景。

管理索引

创建索引

语法格式

CREATE INDEX [ IF NOT EXISTS ] idx_name ON table_name
       USING FULLTEXT (column_name [ , ... ])
       [ WITH ( storage_parameter [ = value ] [ , ... ] ) ];

参数说明

参数

描述

idx_name

索引名。

table_name

目标表名。

column_name

构建全文倒排索引的目标列名。

storage_parameter

配置全文倒排索引参数,有如下两类参数:

  • tokenizer:分词器名称,支持如下分词器:

    • jieba(默认):结合规则匹配与统计模型的中文分词器。

    • whitespace:空格分词器。按空格分词。

    • standard:标准分词器。基于Unicode Standard Annex #29分词。

    • simple:简单分词器。按空格和标点符号分词。

    • keyword:关键词分词器。不进行任何操作,保持原样输出。

    • icu:多语言文本处理分词器。

    • ik:基于IK Analyzer原理实现的中文分词器,可以自动识别英文单词、邮箱、URL(不含://)、IP地址等特殊格式。Hologres V4.0.9版本起支持

    • ngram:基于字符的滑动窗口分词器,通过将文本拆分为连续的n个字符或词(称为n-gram),提升检索系统的召回率和模糊匹配能力。适合like、ilike模糊匹配的加速场景。Hologres V4.0.9版本起支持。

    • pinyin:拼音分词器。对于文本中的中文字和词生成拼音,以及支持对非中文字符串进行拼音拆分推导,帮助用户实现更准确的拼音生成和更高的检索召回率。Hologres V4.0.9版本起支持。

  • analyzer_params:分词器配置,仅支持JSON格式字符串。

    • 每个分词器均有默认的analyzer_params配置,通常情况下,建议使用默认配置,即仅需指定tokenizer参数,无需显式配置analyzer_params参数。

    • 支持自定义其中部分配置,详情请参见高级操作:自定义分词器配置

说明

同一个索引中,仅支持设置一种tokenizer和analyzer_params。

使用示例

  • 创建全文倒排索引,分词器及配置均为默认,即jieba分词器。

    CREATE INDEX idx1 ON tbl 
           USING FULLTEXT (col1);
  • 显式指定使用ik分词器,分词器使用默认配置。

    CREATE INDEX idx1 ON tbl 
           USING FULLTEXT (col1)
           WITH (tokenizer = 'ik');
  • 显式指定使用自定义的分词器配置: jieba分词器+exact模式+仅用lowercase过滤器转小写。

    CREATE INDEX idx1 ON tbl 
           USING FULLTEXT (col1)
           WITH (tokenizer = 'jieba',
                 analyzer_params = '{"tokenizer":{"type":"jieba","mode":"exact"}, "filter":["lowercase"]}');
说明

修改索引

语法格式

-- 修改索引配置
ALTER INDEX [ IF EXISTS ] <idx_name> SET ( <storage_parameter> = '<storage_value>' [ , ... ] );

-- 恢复默认配置
ALTER INDEX [ IF EXISTS ] <idx_name> RESET ( <storage_parameter> [ , ... ] );

参数说明

参数详细说明请参见参数说明

使用示例

说明

修改全文倒排索引后,索引文件将随数据的Compaction过程异步构建。建议在修改索引后,手动执行VACUUM <schema_name>.<table_name>;命令,同步触发Compaction,详情请参见Compaction

  • 将索引的分词器改为standard。

    ALTER INDEX idx1 SET (tokenizer = 'standard');
  • 将索引的分词器改为ik,ik_max_word模式,不转小写,不加任何filter。

    ALTER INDEX idx1 SET (
      tokenizer = 'ik',
      analyzer_params = '{"tokenizer":{"type":"ik","mode":"ik_max_word","enable_lowercase": false}}'
    );
  • 恢复默认分词器jieba,且使用jieba分词器的默认analyzer_params配置。

    ALTER INDEX idx1 RESET (tokenizer);
    ALTER INDEX idx1 RESET (tokenizer, analyzer_params);
  • 恢复到当前分词器的默认analyzer_params配置。

    ALTER INDEX idx1 RESET (analyzer_params);

删除索引

语法格式

DROP INDEX [ IF EXISTS ] <idx_name> [ RESTRICT ];

参数说明

参数详细说明请参见参数说明

查看索引

Hologres提供hologres.hg_index_properties系统表,可查看表中已创建的全文倒排索引及对应位置。

SELECT * FROM hologres.hg_index_properties;

执行如下SQL,可查看索引对应的表和列。

SELECT 
    t.relname AS table_name, 
    a.attname AS column_name
FROM pg_class t
    JOIN pg_index i ON t.oid = i.indrelid
    JOIN pg_class idx ON i.indexrelid = idx.oid
    JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(i.indkey)
WHERE t.relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = '<namespace>')
    AND idx.relname = '<indexname>'
LIMIT 1;

参数说明:

  • namespace:SELECT * FROM hologres.hg_index_properties;命令执行结果中的table_namespace字段值。

  • indexname:为实际创建的索引名称。

使用索引进行全文检索

Hologres支持丰富的检索模式,便于您按照业务逻辑,灵活进行全文检索。

检索模式

说明

关键词匹配

按检索对象的分词结果关键词进行检索,支持定义关键词间的AND/OR关系。

短语检索

按检索对象的短语进行检索,需满足多个词之间的距离要求才可匹配。

自然语言检索

支持自由定义复杂查询条件,灵活实现检索目标,如定义AND/OR关联关系、定义必须出现词/排除词、定义短语等。

术语检索

按检索对象精确检索,需要索引中精确包含查询串才可匹配。

检索函数TEXT_SEARCH

检索函数TEXT_SEARCH可基于检索对象文本,对检索源文本计算BM相关性分数。

函数语法

TEXT_SEARCH (
  <search_data> TEXT/VARCHAR/CHAR
  ,<search_expression> TEXT
  [ ,<mode> TEXT DEFAULT 'match'
  ,<operator> TEXT DEFAULT 'OR'
  ,<tokenizer> TEXT DEFAULT ''
  ,<analyzer_params> TEXT DEFAULT ''
  ,<options> TEXT DEFAULT '']
)

参数说明

参数

是否必填

描述

search_data

检索源。数据类型支持TEXT/VARCHAR/CHAR,仅支持列入参,且列上需已构建全文索引,否则会报错。

search_expression

检索对象。数据类型支持TEXT/VARCHAR/CHAR,仅支持常量。

mode

检索模式。支持的模式如下:

  • match(默认):关键词匹配。每个分词token为一个关键词,多个关键词之间的关系通过operator参数设置,默认为OR。

  • phrase:短语检索。短语中多个词之间的距离通过在options参数中指定slop进行配置,默认为0,即短语中各词必须紧邻。

  • natural_language:自然语言检索。支持使用自然语言表达复杂的查询条件,如AND/OR关键词、必须出现词、必须排除词、短语等。详情请参见Tantivy

  • term:术语检索。对search_expression不做分词或其他处理,直接去索引中精确匹配。

operator

关键词之间的逻辑运算符。仅mode为match时生效。支持如下取值:

  • OR(默认):检索对象有多个分词token时,任意token匹配即可返回。

  • AND:检索对象有多个分词token时,所有token均匹配才可返回。

tokenizeranalyzer_params

对检索对象search_expression使用的分词器及配置,一般无需配置。

  • 不指定时,默认使用与检索源search_data列上全文倒排索引相同的分词器及配置。如检索源为常量,则使用默认分词器jieba。

  • 当指定时,检索对象search_expression将使用指定的分词器及配置进行分词。

options

全文检索的其他参数。入参格式为'key1=v1;key2=v2;....;keyN=vN;'

目前仅支持slop参数,仅mode为phrase时生效,支持slop为0(默认)或正整数,用于定义短语中各个词之间可容忍的距离。

说明

slop表示短语组成词之间的最大允许间隔(或转换开销),对于jieba/keyword/icu等tokenizer来说,间隔的单位是字符数而不是tokens单词数。对于standard/simple/whitespace等tokenizer,间隔的单位是tokens单词数

返回值说明

返回非负的FLOAT类型,表示检索源与检索对象的BM25相关性分数。相关性越高,分数越大。当文本完全不相关时,分数为0。

示例

  • 使用关键词匹配模式,并将运算符改为AND。

    -- 建议指定参数名
    SELECT TEXT_SEARCH (content, 'machine learning', operator => 'AND') FROM tbl;
    
    -- 不指定参数名,需按入参顺序显式指定
    SELECT TEXT_SEARCH (content, 'machine learning', 'match', 'AND') FROM tbl;
  • 使用短语检索模式,并将slop设为2。

    SELECT TEXT_SEARCH (content, 'machine learning', 'phrase', options => 'slop=2;') FROM tbl;
  • 使用自然语言检索模式。

    -- 通过AND、OR运算符定义分词检索逻辑
    SELECT TEXT_SEARCH (content, 'machine AND (system OR recognition)', 'natural_language') FROM tbl;
    
     -- 通过+(必须出现词)、-(必须排除词)定义分词检索逻辑
    SELECT TEXT_SEARCH (content, '+learning -machine system', 'natural_language') FROM tbl;
  • 使用术语检索模式。

    SELECT TEXT_SEARCH (content, 'machine learning', 'term') FROM tbl;

分词函数TOKENIZE

分词函数TOKENIZE可按照分词器配置,输出分词结果,以便对全文倒排索引的分词效果进行调试。

函数语法

TOKENIZE (
  <search_data> TEXT
  [ ,<tokenizer> TEXT DEFAULT ''
  ,<analyzer_params> TEXT DEFAULT '']
)

参数说明

  • search_data:必填。分词目标文本,支持常量入参。

  • tokenizeranalyzer_params:选填。对分词目标文本search_data使用的分词器及配置。默认使用jieba分词器。

返回值说明

返回目标文本的分词token集合,类型为TEXT数组。

索引使用验证

可通过执行计划查看SQL是否使用了全文倒排索引,若其中出现Fulltext Filter,表示已成功使用。执行计划详情请参见EXPLAIN和EXPLAIN ANALYZE

示例SQL:

EXPLAIN ANALYZE SELECT * FROM wiki_articles WHERE text_search(content, '长江') > 0;

执行计划如下:其中包含Fulltext Filter字段,表示该SQL已成功使用全文倒排索引。

QUERY PLAN
Gather  (cost=0.00..1.00 rows=1 width=12)
  ->  Local Gather  (cost=0.00..1.00 rows=1 width=12)
        ->  Index Scan using Clustering_index on wiki_articles  (cost=0.00..1.00 rows=1 width=12)
              Fulltext Filter: (text_search(content, search_expression => '长江'::text, mode => match, operator => OR, tokenizer => jieba, analyzer_params => {"filter":["removepunct","lowercase",{"stop_words":["_english_"],"type":"stop"},{"language":"english","type":"stemmer"}],"tokenizer":{"hmm":true,"mode":"search","type":"jieba"}}, options => ) > '0'::double precision)
Query Queue: init_warehouse.default_queue
Optimizer: HQO version 4.0.0

使用示例

数据准备

执行以下SQL创建测试表、并写入数据。

-- 创建表
CREATE TABLE wiki_articles (id int, content text);

-- 创建索引
CREATE INDEX ft_idx_1 ON wiki_articles
       USING FULLTEXT (content)
       WITH (tokenizer = 'jieba');

-- 写入数据
INSERT INTO wiki_articles VALUES
  (1, '长江是中国第一大河,世界第三长河,全长约6,300公里。'),
  (2, 'Li was born in 1962 in Wendeng County, Shandong.'),
  (3, 'He graduated from the department of physics at Shandong University.'),
  (4, '春节,即农历新年,是中国最重要的传统节日。'),
  (5, '春节通常在公历1月下旬至2月中旬之间。春节期间的主要习俗包括贴春联、放鞭炮、吃年夜饭、拜年等。'),
  (6, '2006年,春节被国务院批准为第一批国家级非物质文化遗产。'),
  (7, 'Shandong has dozens of universities.'),
  (8, 'ShanDa is a famous university of Shandong.');

-- Compaction
VACUUM wiki_articles;

-- 查询表数据
SELECT * FROM wiki_articles limit 1;

返回结果示例如下:

id |                       content                       
---+---------------------------------------------------
 1 | 长江是中国第一大河,世界第三长河,全长约6,300公里。

不同检索示例

  • 关键词匹配。

    -- (K1) 关键词匹配(默认operator=OR),包含'shandong'或'university'的文档均能匹配。
    SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, 'shandong university') > 0;
    
    --返回结果
     id |                               content                               
    ----+---------------------------------------------------------------------
      2 | Li was born in 1962 in Wendeng County, Shandong.
      3 | He graduated from the department of physics at Shandong University.
      7 | Shandong has dozens of universities.
      8 | ShanDa is a famous university of Shandong.
    
    -- (K2) 关键词匹配(operator=AND),必须同时包含'shandong'和'university'才能匹配
    SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, 'shandong university', operator => 'AND') > 0;
    
    -- 返回结果
     id |                               content                               
    ----+---------------------------------------------------------------------
      3 | He graduated from the department of physics at Shandong University.
      7 | Shandong has dozens of universities.
      8 | ShanDa is a famous university of Shandong.
  • 短语检索。

    -- (P1) 短语检索(默认slop = 0),即必须 shandong 后紧接 university 后才匹配
    SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, 'shandong university', mode => 'phrase') > 0;
    
    -- 返回结果
     id |                               content                               
    ----+---------------------------------------------------------------------
      3 | He graduated from the department of physics at Shandong University.
    (1 row)
    
    -- (P2) 短语检索指定slop = 14,即 shandong 与 university 之间的距离不超过14个字符,那么可以匹配“Shandong has dozens of universities.”
    SELECT * FROM wiki_articles
            WHERE TEXT_SEARCH(content, 'shandong university', mode => 'phrase', options => 'slop=14;') > 0;
            
    -- 返回结果
     id |                               content                               
    ----+---------------------------------------------------------------------
      3 | He graduated from the department of physics at Shandong University.
      7 | Shandong has dozens of universities.
    (2 rows)
    
    -- (P3) 短语检索支持检索不保序的短语,但slop计算方式不一样,要比保序的slop要大。
    --      因此'university of Shandong'也能匹配以下查询,但slop=22时不会匹配到
    SELECT * FROM wiki_articles
            WHERE TEXT_SEARCH(content, 'shandong university', mode => 'phrase', options => 'slop=23;') > 0;
            
    -- 返回结果   
     id |                               content                               
    ----+---------------------------------------------------------------------
      3 | He graduated from the department of physics at Shandong University.
      7 | Shandong has dozens of universities.
      8 | ShanDa is a famous university of Shandong.
    (3 rows)
    
    -- (P4) standard分词索引下的表现。(ALTER INDEX ft_idx_1 SET (tokenizer = 'standard');)
    --      对于standard分词来说,slop则是以tokens为计算单位。
    --      只要中间间隔0个tokens,不管有多少空格,都算作短语匹配。
    SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, 'shandong university', mode => 'phrase') > 0;
    
    -- 返回结果
     id |        content         
    ----+------------------------
      1 | shandong university
      2 | shandong  university
      3 | shandong   university
      4 | shandong    university
    (4 rows)
    
    -- (P5) 标点将被忽略。(jieba分词器为例)
    --      即使文本中,长河和全长之间是逗号,而查询串是句号。
    SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, '长河。全长', mode => 'phrase') > 0;
    
    -- 返回结果
     id |                       content                       
    ----+-----------------------------------------------------
      1 | 长江是中国第一大河,世界第三长河,全长约6,300公里。
    (1 row)
  • 自然语言查询。

    -- (N1) 自然语言查询:不加任何符号,默认等同于关键词匹配。与(K1)等价。
    SELECT * FROM wiki_articles
            WHERE TEXT_SEARCH(content, 'shandong university', 'natural_language') > 0;
     id |                               content                               
    ----+---------------------------------------------------------------------
      7 | Shandong has dozens of universities.
      2 | Li was born in 1962 in Wendeng County, Shandong.
      3 | He graduated from the department of physics at Shandong University.
      8 | ShanDa is a famous university of Shandong.
    
    -- (N2) 自然语言查询:关键词匹配,必须(同时包含'shandong'和'university')或者包含'文化'才匹配。AND运算符优先级大于OR。
    SELECT * FROM wiki_articles
            WHERE TEXT_SEARCH(content, '(shandong AND university) OR 文化', 'natural_language') > 0;
    -- 等价于
    SELECT * FROM wiki_articles
            WHERE TEXT_SEARCH(content, 'shandong AND university OR 文化', 'natural_language') > 0;
    -- 等价于
    SELECT * FROM wiki_articles
            WHERE TEXT_SEARCH(content, '(+shandong +university) 文化', 'natural_language') > 0;
    
    -- 返回结果
     id |                               content                               
    ----+---------------------------------------------------------------------
      8 | ShanDa is a famous university of Shandong.
      7 | Shandong has dozens of universities.
      3 | He graduated from the department of physics at Shandong University.
      6 | 2006年,春节被国务院批准为第一批国家级非物质文化遗产。
    
    -- (N3) 自然语言查询:关键词匹配,必须包含'shandong',必须不包含'university',可以包含'文化'。
    --      在这个查询中'文化'关键词前没有+, -符号,不会影响哪些行会匹配上,但会影响匹配分数,带有'文化'的匹配分数更高。
    SELECT * FROM wiki_articles
            WHERE TEXT_SEARCH(content, '+shandong -university 文化', 'natural_language') > 0;
     id |                     content                      
    ----+--------------------------------------------------
      2 | Li was born in 1962 in Wendeng County, Shandong.
    
    -- 必须包含'shandong',必须不包含'physics',可以包含'famous'。包含famous的相关性分数更高。
    -- 注:此Query为单Shard下的分数计算结果,不同的Shard数,不同的文件组织,计算出来的BM25分数可能不一样。
    SELECT id,
           content,
           TEXT_SEARCH(content, '+shandong -physics famous', 'natural_language') as score
    FROM wiki_articles
    WHERE TEXT_SEARCH(content, '+shandong -physics famous', 'natural_language') > 0
    ORDER BY score DESC;
    
    -- 返回结果
     id |                     content                      |  score   
    ----+--------------------------------------------------+----------
      8 | ShanDa is a famous university of Shandong.       |  2.92376
      7 | Shandong has dozens of universities.             | 0.863399
      2 | Li was born in 1962 in Wendeng County, Shandong. | 0.716338
    
    -- (N4) 自然语言查询:短语检索,与(P1)等价,短语需用双引号""包裹,如果中间有",则需使用\转义。
    SELECT * FROM wiki_articles
            WHERE TEXT_SEARCH(content, '"shandong university"', 'natural_language') > 0;
            
    -- 返回结果
     id |                               content                               
    ----+---------------------------------------------------------------------
      3 | He graduated from the department of physics at Shandong University.
    
    -- (N5) 自然语言查询:短语检索,与(P2)等价,支持以~语法设置slop
    SELECT * FROM wiki_articles
            WHERE TEXT_SEARCH(content, '"shandong university"~23', 'natural_language') > 0;
            
    -- 返回结果
     id |                               content                               
    ----+---------------------------------------------------------------------
      8 | ShanDa is a famous university of Shandong.
      7 | Shandong has dozens of universities.
      3 | He graduated from the department of physics at Shandong University.
    
    -- (N6) 自然语言查询:匹配所有文档
    SELECT * FROM wiki_articles                                                                                  
            WHERE TEXT_SEARCH(content, '*', 'natural_language') > 0;
            
    -- 返回结果
     id |                                           content                                            
    ----+----------------------------------------------------------------------------------------------
      1 | 长江是中国第一大河,世界第三长河,全长约6,300公里。
      2 | Li was born in 1962 in Wendeng County, Shandong.
      3 | He graduated from the department of physics at Shandong University.
      4 | 春节,即农历新年,是中国最重要的传统节日。
      5 | 春节通常在公历1月下旬至2月中旬之间。春节期间的主要习俗包括贴春联、放鞭炮、吃年夜饭、拜年等。
      6 | 2006年,春节被国务院批准为第一批国家级非物质文化遗产。
      7 | Shandong has dozens of universities.
      8 | ShanDa is a famous university of Shandong.
  • 术语查询。

    -- (T1) 术语查询:分词结果中,有明确包含"春节",可以检索到
    SELECT * FROM wiki_articles 
             WHERE TEXT_SEARCH(content, '春节', 'term') > 0;
    
    -- 返回结果         
     id |                                           content                                            
    ----+----------------------------------------------------------------------------------------------
      4 | 春节,即农历新年,是中国最重要的传统节日。
      5 | 春节通常在公历1月下旬至2月中旬之间。春节期间的主要习俗包括贴春联、放鞭炮、吃年夜饭、拜年等。
      6 | 2006年,春节被国务院批准为第一批国家级非物质文化遗产。
    
    
    -- (T2) 术语查询:无法查询到结果的示例
    -- 因为检索源表wiki_articles列content默认使用jieba分词器,会将"shandong university"拆分。
    -- 推荐term术语查询和keyword分词器搭配,该场景即可检索到目标数据。
    SELECT * FROM wiki_articles 
             WHERE TEXT_SEARCH(content, 'shandong university', 'term') > 0;
    
    -- 返回结果         
     id | content 
    ----+---------

复杂查询示例

  • 与PK联合查询。

    -- 检索源中包含shandong或university,且id=3的文本。
    SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, 'shandong university') > 0 and id = 3;
    
    -- 返回结果
     id |                               content                               
    ----+---------------------------------------------------------------------
      3 | He graduated from the department of physics at Shandong University.
      
    
    -- 检索源中包含shandong或university,或id<2的文本。
    SELECT * FROM wiki_articles WHERE TEXT_SEARCH(content, 'shandong university') > 0 OR id < 2;
    
    -- 返回结果
     id |                               content                               
    ----+---------------------------------------------------------------------
      2 | Li was born in 1962 in Wendeng County, Shandong.
      8 | ShanDa is a famous university of Shandong.
      1 | 长江是中国第一大河,世界第三长河,全长约6,300公里。
      3 | He graduated from the department of physics at Shandong University.
      7 | Shandong has dozens of universities.
  • 查出分数,并取TOP3。

    SELECT id,
           content,
           TEXT_SEARCH(content, 'shandong university') AS score,
           TOKENIZE(content, 'jieba')
      FROM wiki_articles
    ORDER BY score DESC
    LIMIT 3;
    
    -- 返回结果
    id  |                               content                               |  score  |                     tokenize                     
    ----+---------------------------------------------------------------------+---------+--------------------------------------------------
      8 | ShanDa is a famous university of Shandong.                          | 2.74634 | {shanda,famous,univers,shandong}
      7 | Shandong has dozens of universities.                                | 2.74634 | {shandong,has,dozen,univers}
      3 | He graduated from the department of physics at Shandong University. | 2.38178 | {he,graduat,from,depart,physic,shandong,univers}
  • 同时在output和where中使用TEXT_SEARCH函数。

    SELECT id,
           content,
           TEXT_SEARCH(content, 'shandong university') AS score,
           TOKENIZE(content, 'jieba')
      FROM wiki_articles
     WHERE TEXT_SEARCH(content, 'shandong university') > 0
    ORDER BY score DESC;
    
    -- 返回结果
    id  |                               content                               |  score  |                     tokenize                     
    ----+---------------------------------------------------------------------+---------+--------------------------------------------------
      7 | Shandong has dozens of universities.                                | 2.74634 | {shandong,has,dozen,univers}
      8 | ShanDa is a famous university of Shandong.                          | 2.74634 | {shanda,famous,univers,shandong}
      3 | He graduated from the department of physics at Shandong University. | 2.38178 | {he,graduat,from,depart,physic,shandong,univers}
      2 | Li was born in 1962 in Wendeng County, Shandong.                    | 1.09244 | {li,born,1962,wendeng,counti,shandong}
  • 检索wiki来源中,和shandong university最相关的文档。

    -- 来源表,用于JOIN。
    CREATE TABLE article_source (id int primary key, source text);
    INSERT INTO article_source VALUES (1, 'baike'), (2, 'wiki'), (3, 'wiki'), (4, 'baike'),
                                      (5, 'baike'), (6, 'baike'), (7, 'wiki'), (8, 'paper'),
                                      (9, 'http_log'), (10, 'http_log'), (11, 'http_log');
                                      
    SELECT a.id,
           source, content,
           TEXT_SEARCH(content, 'shandong university') AS score,
           TOKENIZE(a.content, 'jieba')
      FROM wiki_articles a
      JOIN article_source b
        ON (a.id = b.id)
     WHERE TEXT_SEARCH(a.content, 'shandong university') > 0
       AND b.source = 'wiki'
    ORDER BY score DESC;
    
    -- 返回结果
    id  | source |                               content                               |  score  |                     tokenize                     
    ----+--------+---------------------------------------------------------------------+---------+--------------------------------------------------
      7 | wiki   | Shandong has dozens of universities.                                | 2.74634 | {shandong,has,dozen,univers}
      3 | wiki   | He graduated from the department of physics at Shandong University. | 2.38178 | {he,graduat,from,depart,physic,shandong,univers}
      2 | wiki   | Li was born in 1962 in Wendeng County, Shandong.                    | 1.09244 | {li,born,1962,wendeng,counti,shandong}

使用建议

使用Serverless资源重建索引

如果表属性修改,可能触发Compaction并重建索引,带来大量CPU消耗。如有下列表属性修改需求,建议按下文步骤操作:

  • 修改bitmap_columns、dictionary_encoding_columns、向量索引,均会触发Compaction并重建索引,因此不建议使用ALTER TABLE xxx SET语法修改,建议执行如下命令,通过Rebuild语法、使用Serverless Computing资源执行,详情参见REBUILD

ASYNC REBUILD TABLE <table_name> 
WITH (
    rebuild_guc_hg_computing_resource = 'serverless'
)
SET (
    bitmap_columns = '<col1>,<col2>',
    dictionary_encoding_columns = '<col1>:on,<col2>:off',
    vectors = '{
    "<col_vector>": {
        "algorithm": "HGraph",
        "distance_method": "Cosine",
        "builder_params": {
            "base_quantization_type": "rabitq",
            "graph_storage_type": "compressed",
            "max_degree": 64,
            "ef_construction": 400,
            "precise_quantization_type": "fp32",
            "use_reorder": true,
            "max_total_size_to_merge_mb" : 4096
        }
    }
    }'
);
  • 修改列式JSONB列、全文索引列,也会触发Compaction并重建索引,暂不支持通过Rebuild语法执行,建议通过新建临时表方案修改,详见如下步骤:

BEGIN ;
-- 清理潜在的临时表
DROP TABLE IF EXISTS <table_new>;
-- 创建临时表
SET hg_experimental_enable_create_table_like_properties=on;
CALL HG_CREATE_TABLE_LIKE ('<table_new>', 'select * from <table>');
COMMIT ;

-- 对应列开启列式JSONB
ALTER TABLE <table_new> ALTER COLUMN <column_name> SET (enable_columnar_type = ON);
-- 对应列创建全文索引
CREATE INDEX <idx_name> ON <table_new> USING FULLTEXT (column_name);

-- 向临时表插入数据,使用Serverless资源执行,并同步完成索引构建
SET hg_computing_resource = 'serverless';
INSERT INTO <table_new> SELECT * FROM <table>;
ANALYZE <table_new>;

BEGIN ;
-- 删除旧表
DROP TABLE IF EXISTS  <table>;
-- 临时表改名
ALTER TABLE <table_new> RENAME TO <table>;
COMMIT ;
  • 修改其他属性,如distribution_key、clustering_key、segment_key、存储格式等,均建议通过Rebuild语法、使用Serverless Computing资源执行。

高级操作:自定义分词器配置

Hologres建议使用分词器的默认配置,但在全文倒排索引的实际使用过程中,可能出现分词器默认配置不满足业务需求的情况。您可自定义分词器配置,以满足业务更灵活的分词需要。

analyzer_params配置要求

分词器配置参数analyzer_params的配置要求如下:

  • 仅支持JSON格式字符串。

  • JSON顶层支持tokenizer、filter两个键,取值如下:

    • filter:选填,值为JSON数组,用于配置分词过滤属性。如需配置多个分词过滤属性,将严格遵循配置顺序作用到每一个分词token上。

    • tokenizer:必填,值为JSON对象,用于配置分词器属性。JSON对象中支持如下键:

      • type:必填,分词器名称

      • tokenizer对象的其他参数,不同分词器支持的参数不同,详见下表:

        分词器

        tokenizer对象
        的其他参数

        参数说明

        参数取值

        jieba

        mode

        定义分词模式。

        • search(默认):分词时列举多种可能的组合,允许冗余。如“传统节日”的分词结果为“传统”、“节日”和“传统节日”共3个token。

        • exact:分词时不冗余切分。如“传统节日”的分词结果仅为“传统节日”1个token。

        hmm

        定义是否使用隐马尔可夫模型来识别词典中没有的词,以提高新词识别能力。

        • true(默认):使用

        • false:不使用

        standard

        max_token_length

        最大token长度。

        正整数,默认值255。如果遇到超过此长度的token,则会以 max_token_length 为间隔进行拆分。

        ik

        mode

        定义分词模式。

        • ik_max_word(默认):细粒度分词,输出所有可能的短词。如“南京市”的分词结果为“南京”和“市”。

        • ik_smart:粗粒度分词,优先输出长词,减少切分数量。分词输出的token之间不会产生重叠。会尝试将数词和量词组合,作为一个token输出。如“南京市”、“1千米”均不继续分词。

        enable_lowercase

        是否将Token转换成小写。

        • true(默认)

        • false

        ngram

        min_ngram

        Token最小字符长度。

        默认为1。正数。与max_ngram差距最大为3。

        说明:可通过设置如下GUC,调整最大差距值,如SET hg_fulltext_index_max_ngram_diff = 5

        max_ngram

        Token最大字符长度。

        默认为2。取值范围[1, 255]。与min_ngram差距最大为3。

        说明

        当max_ngram与min_ngram差距过大时,ngram分词器会生成大量分词token,导致资源消耗增大、索引存储增加、索引构建时长增加等问题。

        prefix_only

        是否只考虑前缀。

        • true

        • false(默认)

        pinyin

        keep_first_letter

        是否保留每个汉字的首字母。

        • true(默认):保留。如“李明”分词结果包含“lm”。

        • false:不保留。

        keep_separate_first_letter

        是否单独保留每个汉字的首字母。

        • true:保留。如“李明”分词结果包含“l,m”。

        • false(默认):不保留。

        limit_first_letter_length

        首字母结果Token的最大长度。

        保留的首字母串的最大长度。Int类型,默认为16。

        keep_full_pinyin

        是否保留每个汉字的完整拼音。

        • true(默认):保留。如“李明”分词结果包含“li,ming”。

        • false:不保留。

        keep_joined_full_pinyin

        是否连接每个汉字的完整拼音。

        • true:连接。如“李明”分词结果包含“liming”。

        • false(默认):不连接。

        keep_none_chinese

        是否保留结果中的非汉字字母或数字。

        • true(默认):保留。

        • false:不保留。

        keep_none_chinese_together

        是否将非汉字字母或数字保留在一起。

        • true(默认):保留。如“DJ李明”分词结包含“DJ,li,ming”,“DJ”连接在一起。

        • false:不保留如“DJ李明”分词结果包含“D,J,li,ming”。

        说明

        该参数需将keep_none_chinese设为true才生效。

        keep_none_chinese_in_first_letter

        是否在首字母Token中保留非汉字字母或数字。

        • true(默认):保留。如“李明AT2025”分词结果包含“lmat2025”。

        • false:不保留。

        keep_none_chinese_in_joined_full_pinyin

        是否在完整拼音连接的Token中保留非汉字字母或数字。

        • true:保留。如“李明AT2025”分词结果包含“limingat2025”。

        • false(默认):不保留。

        none_chinese_pinyin_tokenize

        如果非汉字字母是拼音,是否拆分为单独的拼音词项。

        • true(默认):拆分。如“limingalibaba2025”分词结果包含“li,ming,a,li,ba,ba,2025”

        • false:不拆分

        说明

        该参数需将keep_none_chinese、keep_none_chinese_together设为true才生效。

        keep_original

        是否保留原始输入。

        • true:保留

        • false(默认):不保留

        lowercase

        是否将非汉字字母小写化处理。

        • true(默认)

        • false

        trim_whitespace

        是否裁剪空白字符。

        • true(默认)

        • false

        remove_duplicated_term

        是否移除重复词项。

        • true,移除。如“de的”分词结果为“de”,但会影响对“de的”的短语查询结果。

        • false(默认),不移除。

        keep_separate_chinese

        是否保留单独汉字。

        • true:保留。如“李明”分词结果包含“李,明”2个Token。

        • false(默认):不保留。

analyzer_params默认配置

不同分词器对应的analyzer_params默认配置如下:

分词器名称

analyzer_params默认配置

分词示例

jieba(默认分词器)

{
  "tokenizer": {
    "type": "jieba", 
    "mode": "search",
    "hmm": true
  }, 
  "filter": [
    "removepunct",
    "lowercase",
    {"type": "stop", "stop_words": ["_english_"]},
    {"type": "stemmer", "language": "english"}
  ]
}
 春节
 ,
 即
 农历
 新年
 ,
 是
 中国
 最
 重要
 的
 传统
 节日
 传统节日
 。

whitespace

{
  "tokenizer": {
    "type": "whitespace"
  }
}
春节,即农历新年,是中国最重要的传统节日。

keyword

{
  "tokenizer": {
    "type": "keyword"
  }
}
春节,即农历新年,是中国最重要的传统节日。

simple

{
  "tokenizer": {
    "type": "simple"
  }, 
  "filter": [
    "lowercase"
  ]
}
春节
即农历新年
是中国最重要的传统节日

standard

{
  "tokenizer": {
    "type": "standard",
    "max_token_length": 255
  }, 
  "filter": [
    "lowercase"
  ]
}
春
节
即
农
历
新
年
是
中
国
最
重
要
的
传
统
节
日

icu

{
  "tokenizer": {
    "type": "icu"
  }, 
  "filter": [
    "removepunct",
    "lowercase"
  ]
}
春节
,
即
农历
新年
,
是
中国
最重
要
的
传统
节日
。

ik

{
  "tokenizer": {
    "type": "ik",
    "mode": "ik_max_word",
    "enable_lowercase": true
  },
  "filter": [
    {"type": "stop", "stop_words": ["_english_"]},
    {"type": "stemmer", "language": "english"}
  ]
}
春节
即
农历
新年
是
中国
最重
重要
的
传统节日
传统
节日

ngram

{
  "tokenizer": {
    "type": "ngram",
    "min_gram": 1,
    "max_gram": 2,
    "prefix_only": false
  }
}
春
春节
节
节,
,
,即
即
即农
农
农历
历
历新
新
新年
年
年,
,
,是
是
是中
中
中国
国
国最
最
最重
重
重要
要
要的
的
的传
传
传统
统
统节
节
节日
日
日。
。

pinyin

{
  "tokenizer": {
    "type": "pinyin",
    "keep_first_letter": true,
    "keep_separate_first_letter": false,
    "keep_full_pinyin": true,
    "keep_joined_full_pinyin": false,
    "keep_none_chinese": true,
    "keep_none_chinese_together": true,
    "none_chinese_pinyin_tokenize": true,
    "keep_original": false,
    "limit_first_letter_length": 16,
    "lowercase": true,
    "trim_whitespace": true,
    "keep_none_chinese_in_first_letter": true,
    "keep_none_chinese_in_joined_full_pinyin": false,
    "remove_duplicated_term": false,
    "ignore_pinyin_offset": true,
    "fixed_pinyin_offset": false,
    "keep_separate_chinese": false
  }
}
chun
cjjnlxnszgzzydct
jie
ji
nong
li
xin
nian
shi
zhong
guo
zui
zhong
yao
de
chuan
tong
jie
ri

analyzer_params中的filter配置

Hologres支持在analyzer_params中配置如下filter(分词过滤属性)。

说明

如果配置了多个分词过滤属性,将严格遵循配置顺序作用到每一个分词token上。

属性名称

属性说明

参数格式

使用示例

lowercase

将token中的大写字母转为小写。

仅需声明lowercase。

"lowercase"
  • 分词过滤属性定义

    "filter": ["lowercase"]
  • 分词过滤结果

    ["Hello", "WORLD"]->["hello", "world"]

stop

移除停用词token。


stop_words: 停用词列表,必须为只包含字符串的列表。支持用户自定义停用词,也支持如下针对部分语言的内置停用词词典:

"_english_"
"_danish_"
"_dutch_"
"_finnish_"
"_french_"
"_german_"
"_hungarian_"
"_italian_"
"_norwegian_"
"_portuguese_"
"_russian_"
"_spanish_"
"_swedish_"
  • 分词过滤属性定义

    "filter": [{
      "type": "stop",
      "stop_words": ["_english_", "cat"]
    }]
  • 分词过滤结果

    ["the", "cat", "is", "on", "a", "mat"]->["mat"]

    说明

    "cat"是用户自定义停用词,"the"、"is"、"on"、"a"是内置"_english_"中包含的停用词。

stemmer

根据对应语言的语法规则,将token转化为其对应的词干。

language:语言,支持如下内置语言。

"arabic",
"danish",
"dutch",
"english",
"finnish",
"french",
"german",
"greek",
"hungarian",
"italian",
"norwegian",
"portuguese",
"romanian",
"russian",
"spanish",
"swedish",
"tamil",
"turkish"
  • 分词过滤属性定义

    "filter": [{
      "type": "stemmer",
      "language": "english"
    }]
  • 分词过滤结果

    ["machine", "learning"]->["machin", "learn"]

length

移除超过指定长度的token。

max:保留的最大长度,必须为正整数。

{"type": "length", "max": 10}
  • 分词过滤属性定义

    "filter": [{"type": "length", "max": 10}]
  • 分词过滤结果

    ["AI", "for", "Artificial", "Intelligence"]->["AI", "for", "Artificial"]

removepunct

移除只包含标点符号字符的token。

仅需声明removepunct。

"removepunct"
说明

自4.0.8开始, removepunct新增mode参数,定义移除模式,取值如下:

  • if_all(默认):仅当token中所有字符均为标点时,才移除该token。

  • if_any:若token中包含任意标点字符,则移除该token。

  • 分词过滤属性定义

    "filter": ["removepunct"]
    说明

    等价于 "filter": [{"type": "removepunct", "mode": "if_all"}]。

  • 分词过滤结果

    ["中文", "english", "中文。", "english.", "124", "124!=8", "。", "、", ",,", " ..."]->["中文", "english", "中文。", "english.", "124", "124!=8"]

    "filter": [{"type": "removepunct", "mode": "if_any"}]

    ["中文", "english", "中文。", "english.", "124", "124!=8", "。", "、", ",,", " ..."] -> ["中文", "english", "124"]

pinyin

拼音Token Filter。

{
  "type": "pinyin",
  "keep_first_letter": true,
  "keep_separate_first_letter": false,
  "keep_full_pinyin": true,
  "keep_joined_full_pinyin": false,
  "keep_none_chinese": true,
  "keep_none_chinese_together": true,
  "none_chinese_pinyin_tokenize": true,
  "keep_original": false,
  "limit_first_letter_length": 16,
  "lowercase": true,
  "trim_whitespace": true,
  "keep_none_chinese_in_first_letter": true,
  "keep_none_chinese_in_joined_full_pinyin": false,
  "remove_duplicated_term": false,
  "ignore_pinyin_offset": true,
  "fixed_pinyin_offset": false,
  "keep_separate_chinese": false
}

Filter配置属性同Pinyin分词器。