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
Regex匹配函數。bm25.regex 對單個詞元進行正則匹配;bm25.regex_phrase 在短語層級進行正則匹配,要求多個詞元按順序出現且每個詞元滿足對應的正則模式。
參數說明:
參數 | 是否必填 | 說明 |
pattern | 是 | Regex模式。 |
field | 否 | 指定查詢的目標欄位名稱。 |
樣本:
WHERE body @@@ bm25.regex('post.*')使用說明:
正則匹配直接作用於索引中的詞元(term),而非原始文檔文本。請根據分詞後的詞元格式編寫Regex。
複雜的Regex可能帶來較高的效能開銷,建議在必要時使用。
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 倍。
適用於多欄位檢索情境,能夠在保留首選欄位主導評分的同時,兼顧其他欄位的匹配貢獻。