Nova BM25 Function API は、WHERE 句で全文検索ロジックを表現するための SQL 関数のセットを提供します。@@@ 演算子と組み合わせることで、これらの関数は BM25 の関連度に基づいた効率的な検索を実現します。
概要
Nova BM25 Function API は、@@@ 演算子を介して、BM25 による全文検索を SQL の WHERE 句に統合します。 @@@ の左辺は BM25 検索の対象列で、右辺は bm25.* クエリ関数です。基本的な構文は次のとおりです:
WHERE body @@@ bm25.match('full-text search')
クエリ関数は 2 つの呼び出しモードをサポートします:
-
現在の列クエリ: クエリ関数は
@@@の左辺で指定された列に直接作用し、追加のフィールド名は不要です。WHERE body @@@ bm25.match('full-text search') -
フィールド指定クエリ:
fieldパラメーターを使用して、対象フィールドを明示的に指定します。このモードは、複数のフィールドにわたる検索条件を必要とする複合クエリに適しています。WHERE body @@@ bm25.boolean( should => ARRAY[ bm25.match('title', query => 'full-text search'), bm25.match('body', query => 'full-text search') ], must_not => ARRAY[ bm25.term('category', 'deleted') ] )
クエリトークナイザー
クエリートークナイザーは、クエリーテキストがどのようにトークン化されるかを制御し、検索マッチングの粒度に影響を与えます。bm25.tokenizer() 関数を使用してトークナイザーインスタンスを作成し、クエリー関数の tokenizer パラメーターに渡します。
WHERE body @@@ bm25.match(
'PostgreSQL BM25',
operator => 'and',
tokenizer => bm25.tokenizer(name => 'default')
)
一般的なトークナイザーを次の表に示します。
|
トークナイザー名 |
説明 |
例 |
|
jieba |
Jieba 中国語トークナイザーで、汎用的な中国語テキストのトークン化に適しています。 |
|
|
default |
ホワイトスペースと句読点でテキストを分割するデフォルトのトークナイザーです。英語、数値、記号を含むテキストに適しています。 |
|
|
keyword |
トークン化は行いません。入力全体を 1 つのトークンとして扱うため、完全一致のシナリオに適しています。 |
|
|
ik_smart |
IK トークナイザーのスマートトークン化モードです。最も粗い粒度で分割します。 |
|
|
ik_max_word |
IK トークナイザーの最大語モードです。より多くの組み合わせをカバーできるよう、最も細かい粒度で分割します。 |
|
|
ngram |
テキストを固定長の部分文字列に分割する N-gram トークナイザーです。細かい粒度での分割、部分一致、オートコンプリートのシナリオに適しています。 |
|
テキストマッチング関数
テキストマッチング関数は、トークン化されたテキストコンテンツに対して関連性に基づく検索を実行します。各関数は、全文マッチング、フレーズマッチング、プレフィックスマッチング、あいまい一致、正規表現マッチングなど、異なるマッチング戦略を提供します。
bm25.match
全文マッチング関数です。クエリテキストをトークン化し、対象フィールドからこれらのトークンを含むドキュメントを検索した後、BM25 アルゴリズムを使用して関連度スコアを計算します。
パラメーター:
|
パラメーター |
必須 |
説明 |
|
query |
はい |
クエリテキスト。現在の列に対するクエリでは、最初の位置引数として直接渡すことができます。フィールドを指定するクエリでは、名前付きパラメーターの |
|
field |
いいえ |
対象フィールドの名前。フィールドをまたがる検索を行う複合クエリでは必須です。 |
|
operator |
いいえ |
トークン間の論理関係。 |
|
tokenizer |
いいえ |
クエリトークナイザーの設定。 |
例:
WHERE body @@@ bm25.match('database search ranking')
WHERE body @@@ bm25.match('database search', operator => 'and')
使用上の注意:
-
operator => 'and'を使用すると、マッチングの精度が向上し、クエリテキスト内のすべてのキーワードに一致する必要のあるシナリオに適しています。 -
デフォルトの
operator => 'or'モードは、より多くのドキュメントに一致し、再現率を優先するシナリオに適しています。
bm25.multi_match
複数フィールド全文マッチング関数です。複数のフィールドにまたがって同時に全文検索を実行し、キャレット (^) 記号を使用して各フィールドに異なる関連度の重みを割り当てることができます。
パラメーター:
|
パラメーター |
必須 |
説明 |
|
fields |
はい |
対象フィールドの配列。各要素はフィールド名です。 |
|
query |
はい |
クエリテキスト。 |
|
operator |
いいえ |
トークン間の論理関係。 |
例:
WHERE body @@@ bm25.multi_match(
ARRAY['title^5', 'body^2'],
query => 'full-text search',
operator => 'or'
)
使用上の注意:
-
重み値が高いほど、そのフィールドのマッチングが最終スコアに与える影響が大きくなります。重みを指定しない場合、デフォルト値は 1 です。
bm25.phrase
フレーズマッチング関数です。トークン化されたクエリテキストのすべてのトークンが、間に他のトークンを挟むことなく、元の順序で連続して出現する必要があります。
パラメーター:
|
パラメーター |
必須 |
説明 |
|
query |
はい |
完全に一致させるフレーズテキスト。 |
|
field |
いいえ |
対象フィールドの名前。 |
例:
WHERE body @@@ bm25.phrase('full-text search')
使用上の注意:
-
フレーズマッチングは全文マッチングよりも厳密であり、トークンの正確な順序が要求されるシナリオに適しています。
bm25.phrase_prefix
フレーズプレフィックスマッチング関数です。トークン化されたクエリテキストのトークンが順序どおりに出現し、かつ最後のトークンがプレフィックスとして一致する必要があります。
パラメーター:
|
パラメーター |
必須 |
説明 |
|
terms |
はい |
トークンの配列。最後の要素はプレフィックスとして一致し、他のすべての要素は完全一致します。 |
|
field |
いいえ |
対象フィールドの名前。 |
例:
WHERE body @@@ bm25.phrase_prefix(ARRAY['post'])
使用上の注意:
-
オートコンプリートや部分入力マッチングのシナリオに適しています。たとえば、ユーザーが部分的なキーワードを入力したときに候補結果を返す場合などです。
bm25.fuzzy_term
あいまいタームマッチング関数です。レーベンシュタイン距離に基づき、クエリトークンがインデックス化されたトークンと、指定された文字編集数まで異なることを許容します。スペル訂正のシナリオに適しています。
パラメーター:
|
パラメーター |
必須 |
説明 |
|
query |
はい |
クエリタームのテキスト。 |
|
field |
いいえ |
対象フィールドの名前。 |
|
distance |
いいえ |
最大編集距離。許容される文字の相違の最大数です。デフォルト値:1。最大値:2。値が大きいほど、マッチングが緩やかになり、パフォーマンスのオーバーヘッドが大きくなります。 |
例:
WHERE body @@@ bm25.fuzzy_term('keybord', distance => 1)
使用上の注意:
-
この例では、
'keybord'は'keyboard'との編集距離が 1 (aの欠落) であるため、'keyboard'を含むドキュメントに一致できます。 -
distance値は 2 以下に保つことを推奨します。編集距離が大きいと、マッチングが広範になりすぎ、パフォーマンスが低下します。
bm25.regex と bm25.regex_phrase
正規表現マッチング関数です。bm25.regex は単一のトークンに対して正規表現マッチングを実行します。bm25.regex_phrase はフレーズレベルで正規表現マッチングを実行するもので、複数のトークンが順序どおりに出現し、各トークンが対応する正規表現パターンを満たす必要があります。
パラメーター:
|
パラメーター |
必須 |
説明 |
|
pattern |
はい |
正規表現パターン。 |
|
field |
いいえ |
対象フィールドの名前。 |
例:
WHERE body @@@ bm25.regex('post.*')
使用上の注意:
-
正規表現マッチングは、元のドキュメントテキストではなく、インデックス内のトークンに対して動作します。トークン化された形式に基づいて正規表現を記述してください。
-
複雑な正規表現は、大きなパフォーマンスのオーバーヘッドを引き起こす可能性があります。必要な場合のみ使用してください。
bm25.span_near
高度な近接マッチング関数です。指定された複数のトークンがドキュメント内で互いに近接して出現する必要があり、トークン間の最大許容ギャップを制御できます。
パラメーター:
|
パラメーター |
必須 |
説明 |
|
clauses |
はい |
スパンクエリ句の配列。例: |
|
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
フィールドの存在をチェックする関数です。指定されたフィールドに非 NULL 値が含まれるドキュメントを検索します。
パラメーター:
この関数にはパラメーターは必要ありません。
例:
WHERE rating @@@ bm25.exists()
使用上の注意:
-
この関数は、特定の値に関係なく、フィールドに値が含まれているかどうかだけをチェックします。特定のフィールド を持たないドキュメントを除外する場合に適しています。
複合クエリ関数
複合クエリ関数は、複数のクエリ条件を組み合わせて複雑な検索ロジックを構成します。ブール結合、重みの調整、定数スコアリング、最適選択の戦略をサポートします。
bm25.boolean
ブール複合クエリ関数は、複数のサブクエリを must (一致必須)、should (一致推奨、スコアに影響)、および must_not (不一致必須) の 3 つのディメンションで結合する関数です。
パラメーター:
|
パラメーター |
必須 |
説明 |
|
must |
いいえ |
一致が必須となるクエリの配列。すべての |
|
should |
いいえ |
一致すべきクエリの配列。 一致するドキュメントはスコアが高くなりますが、一致は必須ではありません。 |
|
must_not |
いいえ |
一致してはならないクエリの配列です。 |
例:
WHERE body @@@ bm25.boolean(
must => ARRAY[bm25.match('body', query => 'database', operator => 'and')],
should => ARRAY[bm25.match('title', query => 'database')],
must_not => ARRAY[bm25.term('category', 'deleted')]
)
使用上の注意:
-
3 つのパラメーターのうち少なくとも 1 つを指定する必要があります。
-
各配列要素には任意の
bm25.*クエリ関数を指定でき、ネストもサポートされています。
bm25.boost
スコアの重み付け関数です。指定したサブクエリの関連性スコアに固定の factor を乗算し、最終スコアにおける特定条件の影響を増減させます。
パラメーター:
|
パラメーター |
必須 |
説明 |
|
factor |
はい |
スコアの乗数です。正の浮動小数点数を指定します。1 より大きい値は重みを増加させ、1 より小さい値は減少させます。 |
|
query |
はい |
重み付けの対象となるクエリ関数です。 |
例:
bm25.boost(5.0, bm25.match('title', query => 'full-text search', operator => 'and'))
使用上の注意:
-
この例では、title フィールドの一致スコアを 5 倍に増幅し、結果で title が一致したドキュメントをより上位にランク付けします。
bm25.const_score
定数スコア関数です。指定したサブクエリの関連性スコアを固定値に置き換え、一致したすべてのドキュメントに同一のスコアを付与します。
パラメーター:
|
パラメーター |
必須 |
説明 |
|
score |
はい |
定数スコアの値です。正の浮動小数点数を指定します。 |
|
query |
はい |
対象のクエリ関数です。ドキュメントのフィルタリングにのみ使用され、スコアは定数値に置き換えられます。 |
例:
WHERE body @@@ bm25.const_score(1.0, bm25.match('body', query => 'database', 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 => 'wireless headphones', operator => 'and')),
bm25.match('description', query => 'wireless headphones', operator => 'and')
],
tie_breaker => 0.2
)
使用上の注意:
-
この例では、title と description の両方が一致した場合、最終スコアは重み付けされた title のスコアに description のスコアの 0.2 倍を加算した値になります。
-
最も一致したフィールドがスコアを支配しつつ、他のフィールドからの寄与も考慮する必要がある複数フィールド検索のシナリオに適しています。