Azure DocumentDB では、逆ランク Fusion (RRF) 関数を使用してベクター検索とフルテキスト検索スコアリングを組み合わせた強力なハイブリッド検索機能がサポートされるようになりました。
ハイブリッド検索とは
ハイブリッド検索では、ベクトルベースと従来のキーワードベースの検索方法の両方の長所を活用して、より関連性の高い正確な検索結果を提供します。 これは、同じドキュメント内のベクター埋め込みとテキスト データを組み合わせることによって実現されます。
-
ベクトル検索: 機械学習モデルを利用して、クエリとドキュメントのセマンティックな意味を理解します。 これにより、コンテキストに対応した検索結果が増え、従来のキーワード検索が不足する可能性がある複雑なクエリに特に役立ちます。 効率的なベクター類似性検索のために、Azure DocumentDB には、HNSW、IVF、DiskANN の 3 つの
cosmosSearch互換 ベクター インデックスが用意されています。 -
フルテキスト検索: Azure DocumentDB では、フルテキスト検索に
$text演算子が使用されます。
次に、ベクター検索とフルテキスト検索の結果を組み合わせて、両方の検索方法の長所を活用した最終的な検索結果を返します。
- 関連性の強化: セマンティック理解とキーワード マッチングを組み合わせることにより、ハイブリッド検索は、さまざまなクエリに対してより関連性の高い結果を提供できます。
- 精度の向上: RRF 関数を使用すると、両方の検索方法の最も適切な結果が優先されます。
- 汎用性: レコメンデーション システム、セマンティック検索、パーソナライズされたコンテンツ検出など、さまざまなユース ケースに適しています。
ハイブリッド検索の使用方法
- テキスト コンテンツとベクター埋め込みの両方を含む、データを格納するコレクションを作成します。
-
演算子を使用して、ベクター埋め込みフィールドにベクター
cosmosSearchを作成します。 -
$text型の標準インデックス作成コマンドを使用して、テキスト フィールドにフルテキスト インデックスを作成します。 - 集計パイプラインを
$search演算子 (ベクター検索用) と$text演算子 (フルテキスト検索の場合) と共に使用し、次に逆数 Rank Fusion を実装して、$unionWith演算子を使用してスコアを結合する手順を実行します。
ハイブリッド検索のインデックスを構成する
ベクトル インデックスを作成する
db.runCommand({
"createIndexes": "yourCollectionName",
"indexes": [
{
"key": {
"vectorField": "cosmosSearch"
},
"name": "vectorIndex",
"cosmosSearchOptions": {
"kind": "vector-diskann", // "vector-ivf" , "vector-hnsw"
"similarity": "cosine", // "l2"
"dimensions": 3072 // Max 16,000
}
}
]
});
フルテキスト インデックスを作成する
db.runCommand({
"createIndexes": "yourCollectionName",
"indexes": [
{
"key": {
"textField": "text"
},
"name": "fullTextIndex"
}
]
});
ハイブリッド検索を実行する
db.hybrid_col.aggregate([
{ $search: { cosmosSearch: { path: "vector", vector: [0.1, 0.2, 0.3], k: 5 } } }, // Vector search
{ $group: { _id: null, vectorResults: { $push: "$$ROOT" } } },
{ $unwind: { path: "$vectorResults", includeArrayIndex: "vectorRank" } },
{ $addFields: { vs_score: { $divide: [1, { $add: ["$vectorRank", 1, 1] }] } } },
{ $project: { _id: "$vectorResults._id", title: "$vectorResults.text", vs_score: 1 } },
{ $unionWith: {
coll: "hybrid_col",
pipeline: [
{ $match: { $text: { $search: "cat" } } },
{ $addFields: { textScore: { $meta: "textScore" } } },
{ $group: { _id: null, textResults: { $push: "$$ROOT" } } },
{ $unwind: { path: "$textResults", includeArrayIndex: "textRank" } },
{ $addFields: { fts_score: { $divide: [1, { $add: ["$textRank", 10, 1] }] } } },
{ $project: { _id: "$_id", title: "$text", fts_score: 1 } }
]
}},
{ $group: {
_id: "$title",
finalScore: { $max: { $add: [{ $ifNull: ["$vs_score", 0] }, { $ifNull: ["$fts_score", 0] }] } }
}},
{ $sort: { finalScore: -1 } }
])
この例では、最初の $search ステージは、クエリ ベクター [0.1, 0.2, 0.3]のベクター フィールドに対してベクター類似性検索を実行し、最も類似したドキュメントの上位 5 つ (k: 5) を返します。
$groupステージでは、すべてのベクター検索結果が、vectorResultsという配列を持つ 1 つのドキュメントにグループ化されます。 この後、 $unwind ステージは vectorResults 配列を分解し、結果ごとに個別のドキュメントを作成し、そのランク (vectorRank) を追加します。 後続の $addFields ステージでは、ランクに基づいて各ベクター検索結果の逆ランク 融合 (RRF) スコアが計算されます。 次に、 $project ステージは、ベクトル検索結果から _id、 title、計算された vs_score を選択します。
テキスト検索フェーズに進み、 $unionWith ステージでは、ベクター検索パイプラインの結果と、別のフルテキスト検索パイプラインの結果が結合されます。 フルテキスト検索フェーズでは、$match演算子を使用した $text ステージで、テキスト フィールド内の "cat" という用語のフルテキスト検索が実行されます。
$addFields ステージは、textScore 演算子によって割り当てられた関連性スコア ($text) を取得します。 ベクター検索結果と同様に、 $group ステージではすべてのフルテキスト検索結果がグループ化され、 $unwind ステージによって textResults 配列が分解され、ランク (textRank) が追加されます。 ここでは別のペナルティ (10) が使用され、調整できます。
$project ステージでは、フルテキスト検索結果から_id、title、およびfts_scoreを選択します。 結果を組み合わせた後、 $group ステージはドキュメントを title別にグループ化します。
最後に、$projectステージは、ベクター RRF スコア (finalScore) とそのフルテキスト RRF スコア (vs_score) を最大限に活用して、各ドキュメントのfts_scoreを計算します。
$ifNull は、ドキュメントが検索結果の 1 つにのみ存在する可能性があるケースを処理します。
制限事項
- 現在、Azure DocumentDB のフルテキスト検索では、ゲート プレビューでの BM25 ランク付けのみがサポートされています。
- 現時点では、ハイブリッド検索を直接実行する専用のコマンドは 1 つもありません。 上記の例に示すように、集計パイプラインを使用してハイブリッド検索クエリを作成する必要があります。