Nova BM25索引和词典管理
本文介绍如何创建和管理 Nova BM25 全文检索索引,以及如何配置中文分词词典。Nova BM25 是 AnalyticDB PostgreSQL 提供的高性能全文检索方案,基于 nova_bm25 扩展实现,SQL 函数位于 bm25 schema,索引访问方法名为 nova_bm25。
有关 Nova BM25 的快速入门指南,请参见Nova BM25快速开始。有关完整的函数 API 参考,请参见Nova BM25 Function API参考。
创建索引
创建示例表
以下示例创建一个包含多种字段类型的业务表,涵盖文本、数值、时间戳和布尔类型,作为后续索引创建的参考:
CREATE TABLE docs (
id bigint PRIMARY KEY,
title text,
body text,
category text,
rating integer,
publish_at timestamp,
in_stock boolean
) DISTRIBUTED BY (id);创建 BM25 索引
在示例表上创建 Nova BM25 索引,通过 WITH 子句为每种字段类型指定相应的索引配置。正确的字段配置直接影响检索的准确性和性能:
CREATE INDEX docs_bm25_idx ON docs
USING nova_bm25 (title, body, category, rating, publish_at, in_stock)
WITH (
text_fields = '{
"title": {"tokenizer": {"type": "jieba"}},
"body": {"tokenizer": {"type": "jieba"}},
"category": {"tokenizer": {"type": "keyword"}}
}',
numeric_fields = '{"rating": {}}',
datetime_fields = '{"publish_at": {}}',
boolean_fields = '{"in_stock": {}}'
);索引字段配置说明
创建索引时,需要通过 WITH 子句为每个参与检索的字段指定配置。下表列出各类字段配置参数的详细说明:
配置参数 | 适用字段类型 | 说明 | 配置示例 |
| text、varchar | 文本字段,需指定 tokenizer 类型以控制分词方式 |
|
| integer、bigint、float 等 | 数值字段,支持范围查询和数值排序 |
|
| timestamp、date | 时间字段,支持时间范围查询 |
|
| boolean | 布尔字段,支持 true/false 过滤 |
|
| json、jsonb |
|
|
选择字段配置
为每个字段选择正确的配置类型是构建高效全文索引的关键。配置类型决定了字段的检索行为和可用的查询方式。下表列出常见的字段用途及其推荐的配置方式:
字段用途 | 配置方式 | 示例 |
中文标题、正文 |
| title、body |
分类、状态等整值字段 |
| category、status |
评分、价格等数值字段 |
| rating、price |
发布时间等时间字段 |
| publish_at |
是否上架等布尔字段 |
| in_stock |
JSON 字段 |
| metadata |
文本字段 tokenizer 选择指南
为文本字段选择正确的 tokenizer 直接影响检索效果。下表列出常用的 tokenizer 类型及其适用场景:
Tokenizer 类型 | 适用场景 | 说明 |
| 中文文本 | 基于结巴分词,支持中文语义分词,可加载自定义词典 |
| 英文文本 | 按空格和标点符号分词,适用于英文等西文语言 |
| 精确匹配字段 | 不分词,将整个字段值作为一个检索单元,适用于分类、标签、状态码等 |
| 细粒度匹配 | 按 n-gram 切分文本,支持部分匹配和模糊检索,适用于前缀或子串搜索场景 |
验证分词效果
创建索引后,建议使用分词调试函数验证实际的分词效果是否符合预期。以下示例展示如何查看 jieba 分词器对输入文本的分词结果:
SELECT * FROM bm25.debug_tokenizer('云原生数据库', 'jieba');查询增量数据
Nova BM25 支持近实时查询模式,新写入或更新的数据在短暂的延迟后即可被检索到。您可以通过以下参数和命令控制增量数据的查询行为,在数据新鲜度与查询性能之间取得平衡。
通过 query_skip_mutable 参数控制是否查询最新增量数据:
参数 | 说明 |
query_skip_mutable | 默认值为 |
在创建索引时设置该参数:
CREATE INDEX docs_bm25_idx ON docs
USING nova_bm25 (title, body)
WITH (text_fields = '{"title": {"tokenizer": {"type": "jieba"}}, "body": {"tokenizer": {"type": "jieba"}}}', query_skip_mutable = false);通过 ALTER INDEX 修改该参数:
ALTER INDEX docs_bm25_idx SET (query_skip_mutable = false);
ALTER INDEX docs_bm25_idx SET (query_skip_mutable = true);通过 SET 命令在会话级别控制:
SET nova_bm25.query_include_mutable = on;
RESET nova_bm25.query_include_mutable;修改和重建索引
Nova BM25 索引创建后,其字段配置(如 tokenizer 类型、字段映射等)不支持通过 ALTER INDEX 直接修改。如需变更索引配置,必须先删除索引再重新创建。
删除并重新创建索引以修改配置:
DROP INDEX docs_bm25_idx;
-- 重新创建
CREATE INDEX docs_bm25_idx ON docs USING nova_bm25 (...) WITH (...);如果索引配置无需变更,但需要清理索引碎片或刷新索引数据,可以使用 REINDEX 命令重建索引:
REINDEX INDEX docs_bm25_idx;中文词典管理
Nova BM25 使用 jieba 分词器处理中文文本。为了满足业务场景中的专业术语和同义词检索需求,您可以通过词典管理功能自定义分词行为。
添加自定义词条
向 jieba 分词器的自定义词典中添加专业术语或业务词汇,使分词器能够正确识别这些词条,避免被错误切分。添加后需要重新加载词典使其生效:
SELECT bm25.add_dict_word('jieba', 'product_terms', '云原生数据库', 10000, 'n');
SELECT bm25.reload_dict('jieba', 'product_terms');配置同义词
配置同义词词典,将多个含义相近的词条映射到相同的检索结果,从而扩大搜索覆盖面,提升召回率:
SELECT bm25.add_dict_word('synonym', 'product_synonyms', 'postgresql,postgres,pg');
SELECT bm25.reload_dict('synonym', 'product_synonyms');验证词典效果
添加自定义词条或同义词后,建议通过分词调试函数验证词典配置是否生效,确认词条被正确识别:
SELECT * FROM bm25.debug_tokenizer('云原生数据库', 'jieba');日常维护
定期执行维护操作有助于保持 Nova BM25 索引的查询性能和数据一致性。下表列出常用的维护操作及其用途:
操作 | 说明 |
| 回收已删除数据占用的空间,优化表存储 |
| 重建索引以消除碎片,恢复查询性能 |
| 删除不再使用的索引,释放存储空间 |
VACUUM docs;
REINDEX INDEX docs_bm25_idx;
DROP INDEX docs_bm25_idx;