Nova BM25 Function API参考
Nova BM25 Function API 提供一组 SQL 函数,用于在 WHERE 条件中表达全文检索逻辑,结合 @@@ 操作符实现高效的 BM25 相关性检索。
概述
Nova BM25 Function API 通过 @@@ 操作符将 BM25 全文检索能力嵌入 SQL 的 WHERE 子句。@@@ 左侧为参与 BM25 检索的目标列,右侧为 bm25.* 查询函数。基本语法如下:
WHERE body @@@ bm25.match('全文检索')查询函数支持两种调用方式:
当前列查询:查询函数直接作用于
@@@左侧指定的列,无需额外指定字段名。WHERE body @@@ bm25.match('全文检索')指定字段查询:通过
field参数显式指定要查询的字段,适用于组合查询等需要跨多个字段构建检索条件的场景。WHERE body @@@ bm25.boolean( should => ARRAY[ bm25.match('title', query => '全文检索'), bm25.match('body', query => '全文检索') ], must_not => ARRAY[ bm25.term('category', 'deleted') ] )
查询分词器
查询分词器(tokenizer)控制查询文本的分词方式,影响检索的匹配粒度。通过 bm25.tokenizer() 函数创建分词器实例,并传递给查询函数的 tokenizer 参数。
WHERE body @@@ bm25.match(
'PostgreSQL BM25',
operator => 'and',
tokenizer => bm25.tokenizer(name => 'default')
)常用分词器如下:
分词器名称 | 适用场景 | 示例 |
jieba | 结巴中文分词,适用于中文文本的通用分词场景。 |
|
default | 默认分词器,按空白字符和标点进行分词,适用于英文、数字及符号文本。 |
|
keyword | 不分词,将整个输入作为一个单个词元(token),适用于精确值匹配场景。 |
|
ik_smart | IK 分词器的智能分词模式,进行最粗粒度的拆分。 |
|
ik_max_word | IK 分词器的最大词元模式,进行最细粒度的拆分,覆盖更多可能的组合。 |
|
ngram | N-gram 分词器,将文本拆分为固定长度的子串,适用于细粒度切分、部分匹配和自动补全场景。 |
|
文本匹配函数
文本匹配函数用于对文本内容进行分词后的相关性检索。不同的函数提供不同的匹配策略,包括全文匹配、短语匹配、前缀匹配、模糊匹配和正则匹配等。
bm25.match
全文匹配函数。将查询文本经过分词处理后,在目标字段中检索包含这些词元的文档,并按 BM25 算法计算相关性评分。
参数说明:
参数 | 是否必填 | 说明 |
query | 是 | 查询文本。当前列查询时可作为第一个位置参数直接传入;指定字段查询时需通过 |
field | 否 | 指定查询的目标字段名称。在组合查询中需要跨字段检索时必须指定。 |
operator | 否 | 词元之间的逻辑关系。取值为 |
tokenizer | 否 | 查询分词器配置。通过 |
示例:
WHERE body @@@ bm25.match('数据库检索排序')
WHERE body @@@ bm25.match('数据库检索', operator => 'and')使用说明:
使用
operator => 'and'可以提高匹配的精确度,适用于要求查询文本中的所有关键词均命中的场景。默认的
operator => 'or'模式可匹配更多文档,适用于召回优先的场景。
bm25.multi_match
多字段全文匹配函数。同时在多个字段上执行全文检索,并支持通过权重符号(^)为不同字段设置不同的相关性权重。
参数说明:
参数 | 是否必填 | 说明 |
fields | 是 | 目标字段数组。每个元素为字段名称,可通过 |
query | 是 | 查询文本。 |
operator | 否 | 词元之间的逻辑关系。取值为 |
示例:
WHERE body @@@ bm25.multi_match(
ARRAY['title^5', 'body^2'],
query => '全文检索',
operator => 'or'
)使用说明:
权重值越高,该字段的匹配结果对最终评分的贡献越大。未指定权重时默认为 1。
bm25.phrase
短语匹配函数。要求查询文本分词后的所有词元按原始顺序连续出现,词元之间不允许间隔其他词元。
参数说明:
参数 | 是否必填 | 说明 |
query | 是 | 要精确匹配的短语文本。 |
field | 否 | 指定查询的目标字段名称。 |
示例:
WHERE body @@@ bm25.phrase('全文检索')使用说明:
短语匹配比全文匹配更严格,适用于需要精确匹配词序的场景。
bm25.phrase_prefix
短语前缀匹配函数。要求查询文本分词后的词元按顺序出现,其中最后一个词元按前缀方式匹配。
参数说明:
参数 | 是否必填 | 说明 |
terms | 是 | 词元数组。数组中最后一个元素按前缀匹配,其余元素按精确匹配。 |
field | 否 | 指定查询的目标字段名称。 |
示例:
WHERE body @@@ bm25.phrase_prefix(ARRAY['post'])使用说明:
适用于自动补全或部分输入匹配的场景,例如用户输入部分关键词时返回候选结果。
bm25.fuzzy_term
模糊词元匹配函数。基于编辑距离(Levenshtein Distance)允许查询词元与索引中的词元存在一定差异,适用于拼写纠错场景。
参数说明:
参数 | 是否必填 | 说明 |
query | 是 | 查询词元文本。 |
field | 否 | 指定查询的目标字段名称。 |
distance | 否 | 最大编辑距离,即允许的最大字符差异数。默认值为 1,最大支持 2。值越大匹配越宽松,性能开销也越高。 |
示例:
WHERE body @@@ bm25.fuzzy_term('keybord', distance => 1)使用说明:
上述示例中,
'keybord'与'keyboard'的编辑距离为 1(缺少一个字母e),因此可以匹配到包含'keyboard'的文档。建议将
distance控制在 2 以内,过大的编辑距离会导致匹配范围过广且性能下降。
bm25.regex 和 bm25.regex_phrase
正则表达式匹配函数。bm25.regex 对单个词元进行正则匹配;bm25.regex_phrase 在短语级别进行正则匹配,要求多个词元按顺序出现且每个词元满足对应的正则模式。
参数说明:
参数 | 是否必填 | 说明 |
pattern | 是 | 正则表达式模式。 |
field | 否 | 指定查询的目标字段名称。 |
示例:
WHERE body @@@ bm25.regex('post.*')使用说明:
正则匹配直接作用于索引中的词元(term),而非原始文档文本。请根据分词后的词元格式编写正则表达式。
复杂的正则表达式可能带来较高的性能开销,建议在必要时使用。
bm25.span_near
高级邻近匹配函数。要求多个指定词元在文档中彼此靠近出现,且可控制词元间的最大允许间隔。
参数说明:
参数 | 是否必填 | 说明 |
clauses | 是 | Span 子句数组,每个元素为一个 |
slop | 是 | 允许的最大间隔词元数。值为 0 表示所有词元必须紧邻且按顺序出现。 |
示例:
WHERE body @@@ bm25.span_near(
ARRAY[bm25.span_term('postgresql'), bm25.span_term('bm25')],
2
)使用说明:
上述示例要求词元
'postgresql'和'bm25'之间最多间隔 2 个词元。此函数为高级功能,适用于需要精确控制词元位置关系的复杂检索场景。
精确值和范围函数
精确值和范围函数用于对字段值进行精确匹配或范围过滤,不涉及分词处理,适用于关键词、数值、日期等类型的字段。
bm25.term
精确值匹配函数。检索字段值与指定值完全相等的文档,不进行分词处理。
参数说明:
参数 | 是否必填 | 说明 |
value | 是 | 要精确匹配的值,支持字符串、数值等类型。 |
field | 否 | 指定查询的目标字段名称。在组合查询中需要跨字段检索时必须指定。 |
示例:
WHERE tag @@@ bm25.term('search')
WHERE rating @@@ bm25.term(5)使用说明:
对于字符串类型的字段,匹配区分大小写。
bm25.term_set
多值精确匹配函数。检索字段值与指定值集合中任意一个值完全相等的文档。
参数说明:
参数 | 是否必填 | 说明 |
values | 是 | 要匹配的值数组。字段值与数组中任意一个元素相等即视为匹配。 |
field | 否 | 指定查询的目标字段名称。 |
示例:
WHERE tag @@@ bm25.term_set(ARRAY['database', 'search'])使用说明:
等价于对多个值执行
OR精确匹配,比组合多个bm25.term查询更简洁高效。
bm25.range
范围匹配函数。检索字段值落在指定范围内的文档,支持 PostgreSQL 的范围类型语法。
参数说明:
参数 | 是否必填 | 说明 |
range | 是 | PostgreSQL 范围值。使用标准范围语法指定上下界: |
field | 否 | 指定查询的目标字段名称。 |
示例:
WHERE rating @@@ bm25.range('[4,)'::int4range)使用说明:
上述示例匹配
rating大于等于 4 的所有文档。范围类型需与字段的数据类型匹配,常用范围类型包括
int4range(整数)、numrange(数值)、tsrange(时间戳)等。
bm25.exists
字段存在性检查函数。检索指定字段存在值(非空)的文档。
参数说明:
该函数无需参数。
示例:
WHERE rating @@@ bm25.exists()使用说明:
仅检查字段是否存在值,不关心具体的值内容。适用于过滤掉缺少某个字段的文档。
组合查询函数
组合查询函数用于将多个查询条件组合为复杂的检索逻辑,支持布尔组合、权重调整、固定评分和最优选择等策略。
bm25.boolean
布尔组合查询函数。将多个子查询按 must(必须匹配)、should(应当匹配,影响评分)、must_not(必须不匹配)三个维度进行组合。
参数说明:
参数 | 是否必填 | 说明 |
must | 否 | 必须匹配的查询数组。所有 |
should | 否 | 应当匹配的查询数组。匹配的文档评分更高,但非强制要求。当不存在 |
must_not | 否 | 必须不匹配的查询数组。满足 |
示例:
WHERE body @@@ bm25.boolean(
must => ARRAY[bm25.match('body', query => '数据库', operator => 'and')],
should => ARRAY[bm25.match('title', query => '数据库')],
must_not => ARRAY[bm25.term('category', 'deleted')]
)使用说明:
三个参数至少需要指定一个。
每个数组元素可以是任意
bm25.*查询函数,支持嵌套组合。
bm25.boost
评分加权函数。将指定子查询的相关性评分乘以固定倍数,用于提升或降低特定条件对最终评分的影响。
参数说明:
参数 | 是否必填 | 说明 |
factor | 是 | 评分倍数,正浮点数。大于 1 提升权重,小于 1 降低权重。 |
query | 是 | 要加权的目标查询函数。 |
示例:
bm25.boost(5.0, bm25.match('title', query => '全文检索', operator => 'and'))使用说明:
上述示例将标题字段的匹配评分放大 5 倍,使标题匹配的结果在排序中更靠前。
bm25.const_score
固定评分函数。将指定子查询的相关性评分替换为固定值,使所有匹配文档获得相同的评分。
参数说明:
参数 | 是否必填 | 说明 |
score | 是 | 固定的评分值,正浮点数。 |
query | 是 | 目标查询函数。仅用于过滤文档,评分被替换为固定值。 |
示例:
WHERE body @@@ bm25.const_score(1.0, bm25.match('body', query => '数据库', operator => 'and'))使用说明:
适用于只需要过滤而不需要按相关性排序的场景,或者需要为所有匹配文档赋予相同权重的组合查询。
bm25.disjunction_max
最优选择查询函数。从多个子查询中选取评分最高的结果作为最终评分,并可通过 tie_breaker 参数对其他匹配子查询的评分给予一定的附加权重。
参数说明:
参数 | 是否必填 | 说明 |
disjuncts | 是 | 子查询数组。最终评分取其中评分最高的子查询得分。 |
tie_breaker | 否 | 附加权重系数,取值范围 |
示例:
WHERE description @@@ bm25.disjunction_max(
disjuncts => ARRAY[
bm25.boost(3.0, bm25.match('title', query => '无线耳机', operator => 'and')),
bm25.match('description', query => '无线耳机', operator => 'and')
],
tie_breaker => 0.2
)使用说明:
上述示例中,如果标题和描述同时匹配,最终评分为标题的加权评分加上描述评分的 0.2 倍。
适用于多字段检索场景,能够在保留最佳匹配字段主导评分的同时,兼顾其他字段的匹配贡献。