Nova BM25 Function API参考

更新时间:
复制 MD 格式

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

结巴中文分词,适用于中文文本的通用分词场景。

bm25.tokenizer(name => 'jieba')

default

默认分词器,按空白字符和标点进行分词,适用于英文、数字及符号文本。

bm25.tokenizer(name => 'default')

keyword

不分词,将整个输入作为一个单个词元(token),适用于精确值匹配场景。

bm25.tokenizer(name => 'keyword')

ik_smart

IK 分词器的智能分词模式,进行最粗粒度的拆分。

bm25.tokenizer(name => 'ik_smart')

ik_max_word

IK 分词器的最大词元模式,进行最细粒度的拆分,覆盖更多可能的组合。

bm25.tokenizer(name => 'ik_max_word')

ngram

N-gram 分词器,将文本拆分为固定长度的子串,适用于细粒度切分、部分匹配和自动补全场景。

bm25.tokenizer(name => 'ngram')

文本匹配函数

文本匹配函数用于对文本内容进行分词后的相关性检索。不同的函数提供不同的匹配策略,包括全文匹配、短语匹配、前缀匹配、模糊匹配和正则匹配等。

bm25.match

全文匹配函数。将查询文本经过分词处理后,在目标字段中检索包含这些词元的文档,并按 BM25 算法计算相关性评分。

参数说明:

参数

是否必填

说明

query

是

查询文本。当前列查询时可作为第一个位置参数直接传入;指定字段查询时需通过 query 命名参数传入。

field

否

指定查询的目标字段名称。在组合查询中需要跨字段检索时必须指定。

operator

否

词元之间的逻辑关系。取值为 or(默认)表示任一词元匹配即可,取值为 and 表示所有词元均须匹配。

tokenizer

否

查询分词器配置。通过 bm25.tokenizer(name => '...') 指定,详情请参见查询分词器。

示例:

WHERE body @@@ bm25.match('数据库检索排序')
WHERE body @@@ bm25.match('数据库检索', operator => 'and')

使用说明:

  • 使用 operator => 'and' 可以提高匹配的精确度,适用于要求查询文本中的所有关键词均命中的场景。

  • 默认的 operator => 'or' 模式可匹配更多文档,适用于召回优先的场景。

bm25.multi_match

多字段全文匹配函数。同时在多个字段上执行全文检索,并支持通过权重符号(^)为不同字段设置不同的相关性权重。

参数说明:

参数

是否必填

说明

fields

是

目标字段数组。每个元素为字段名称,可通过 ^ 符号设置权重(例如 'title^5' 表示 title 字段的权重为 5)。

query

是

查询文本。

operator

否

词元之间的逻辑关系。取值为 or(默认)或 and。

示例:

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

是

正则表达式模式。bm25.regex 接受单个字符串;bm25.regex_phrase 接受字符串数组,每个元素对应短语中一个位置的匹配模式。

field

否

指定查询的目标字段名称。

示例:

WHERE body @@@ bm25.regex('post.*')

使用说明:

  • 正则匹配直接作用于索引中的词元(term),而非原始文档文本。请根据分词后的词元格式编写正则表达式。

  • 复杂的正则表达式可能带来较高的性能开销,建议在必要时使用。

bm25.span_near

高级邻近匹配函数。要求多个指定词元在文档中彼此靠近出现,且可控制词元间的最大允许间隔。

参数说明:

参数

是否必填

说明

clauses

是

Span 子句数组,每个元素为一个 bm25.span_term() 调用,指定需要邻近出现的词元。

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 范围值。使用标准范围语法指定上下界:[a,b] 表示闭区间,(a,b) 表示开区间,[a,) 表示从 a 到正无穷。需通过类型转换指定数据类型(如 ::int4range)。

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

否

必须匹配的查询数组。所有 must 条件均须满足,且对相关性评分有贡献。

should

否

应当匹配的查询数组。匹配的文档评分更高,但非强制要求。当不存在 must 条件时,至少一个 should 条件须匹配。

must_not

否

必须不匹配的查询数组。满足 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

否

附加权重系数,取值范围 [0.0, 1.0]。当多个子查询同时匹配时,将其余子查询的评分乘以该系数后叠加到最高分上。默认值为 0,即仅取最高分。

示例:

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 倍。

  • 适用于多字段检索场景,能够在保留最佳匹配字段主导评分的同时,兼顾其他字段的匹配贡献。