全部产品
Search
文档中心

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

更新时间:Dec 19, 2025

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 = 'jieba',
      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}

不同分词器示例

  • 使用默认jieba分词器,默认为search模式,会多分词型提高搜索效果。

    SELECT TOKENIZE('他来到北京清华大学', 'jieba');
    
    -- 返回结果
                    tokenize                
    --------------------------------------
    {他,来到,北京,清华,华大,大学,清华大学}
  • 使用自定义的exact模式的jieba分词器,不会多分出词型。

    SELECT TOKENIZE('他来到北京清华大学', 'jieba', '{"tokenizer": {"type": "jieba", "mode": "exact"}}');
    
    -- 返回结果
            tokenize         
    -----------------------
    {他,来到,北京,清华大学}
  • 分词器对比(各自使用默认配置)。

    SELECT TOKENIZE('他来到北京清华大学', 'jieba') as jieba,
           TOKENIZE('他来到北京清华大学', 'ik') as ik,
           TOKENIZE('他来到北京清华大学', 'keyword') as keyword,
           TOKENIZE('他来到北京清华大学', 'whitespace') as whitespace,
           TOKENIZE('他来到北京清华大学', 'simple') as simple,
           TOKENIZE('他来到北京清华大学', 'standard') as standard,
           TOKENIZE('他来到北京清华大学', 'icu') as icu,
           TOKENIZE('他来到北京清华大学', 'ngram') as ngram,
           TOKENIZE('他来到北京清华大学', 'pinyin') as pinyin;
             
    -- 返回结果
    -[ RECORD 1 ]--------------------------------------------------------------------
    jieba      | {他,来到,北京,清华,华大,大学,清华大学}
    ik         | {他,来到,北京,清华大学,清华,大学}
    keyword    | {他来到北京清华大学}
    whitespace | {他来到北京清华大学}
    simple     | {他来到北京清华大学}
    standard   | {他,来,到,北,京,清,华,大,学}
    icu        | {他,来到,北京,清华大学}
    ngram      | {他,他来,来,来到,到,到北,北,北京,京,京清,清,清华,华,华大,大,大学,学}
    pinyin     | {ta,tldbjqhdx,lai,dao,bei,jing,qing,hua,da,xue}
  • 对http_logs的分词效果对比。

    SELECT TOKENIZE('211.11.X.X - - [1998-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0', 'jieba') as jieba,
           TOKENIZE('211.11.X.X - - [1998-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0', 'ik') as ik,
           TOKENIZE('211.11.X.X - - [1998-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0', 'keyword') as keyword,
           TOKENIZE('211.11.X.X - - [1998-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0', 'whitespace') as whitespace,
           TOKENIZE('211.11.X.X - - [1998-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0', 'simple') as simple,
           TOKENIZE('211.11.X.X - - [1998-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0', 'standard') as standard,
           TOKENIZE('211.11.X.X - - [1998-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0', 'icu') as icu,
           TOKENIZE('211.11.X.X - - [1998-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0', 'ngram') as ngram,
           TOKENIZE('211.11.X.X - - [1998-06-21T15:00:01-05:00] \"GET /english/index.html HTTP/1.0\" 304 0', 'pinyin') as pinyin;
           
    -- 返回结果       
    -[ RECORD 1 ]-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    jieba      | {211.11,9.0,1998-06,21t15,00,01-05,00,get,english,index,html,http,1.0,304,0}
    ik         | {211.11.X.X,1998-06-21t15,1998,06,21,t,15,00,01-05,01,05,00,get,english,index.html,index,html,http,1.0,304,0}
    keyword    | {"211.11.X.X - - [1998-06-21T15:00:01-05:00] \\\"GET /english/index.html HTTP/1.0\\\" 304 0"}
    whitespace | {211.11.X.X,-,-,[1998-06-21T15:00:01-05:00],"\\\"GET",/english/index.html,"HTTP/1.0\\\"",304,0}
    simple     | {211,11,9,0,1998,06,21t15,00,01,05,00,get,english,index,html,http,1,0,304,0}
    standard   | {211.11.X.X,1998,06,21t15,00,01,05,00,get,english,index.html,http,1.0,304,0}
    icu        | {211.11.X.X,1998,06,21t15,00,01,05,00,get,english,index.html,http,1.0,304,0}
    ngram      | {2,21,1,11,1,1.,.,.1,1,11,1,1.,.,.9,9,9.,.,.0,0,"0 "," "," -",-,"- "," "," -",-,"- "," "," [",[,[1,1,19,9,99,9,98,8,8-,-,-0,0,06,6,6-,-,-2,2,21,1,1T,T,T1,1,15,5,5:,:,:0,0,00,0,0:,:,:0,0,01,1,1-,-,-0,0,05,5,5:,:,:0,0,00,0,0],],"] "," "," \\","\\","\\\"","\"","\"G",G,GE,E,ET,T,"T "," "," /",/,/e,e,en,n,ng,g,gl,l,li,i,is,s,sh,h,h/,/,/i,i,in,n,nd,d,de,e,ex,x,x.,.,.h,h,ht,t,tm,m,ml,l,"l "," "," H",H,HT,T,TT,T,TP,P,P/,/,/1,1,1.,.,.0,0,"0\\","\\","\\\"","\"","\" "," "," 3",3,30,0,04,4,"4 "," "," 0",0}
    pinyin     | {211119019980621,211119019980621t,t,1500010500,ge,teng,li,shi,n,de,x,h,t,m,l,h,t,t,p,103040}

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

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分词器。