你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

基于 vCore 的 Azure Cosmos DB for MongoDB 中的混合搜索

Azure Cosmos DB for MongoDB(vCore)现在支持强大的混合搜索功能,该功能使用倒数排名融合(RRF)函数将矢量搜索与全文搜索评分相结合。

混合搜索利用基于矢量和基于关键字的传统搜索方法的优势来提供更相关和更准确的搜索结果。 这可以通过合并同一文档中的矢量嵌入和文本数据来实现:

  • 矢量搜索:利用机器学习模型了解查询和文档的语义含义。 这使得搜索结果能够更好地感知上下文,对于传统关键字搜索可能无法充分处理的复杂查询尤其有用。 为了进行高效的矢量相似性搜索,Azure Cosmos DB for MongoDB 提供三cosmosSearch个兼容的矢量索引:HNSW、IVF 和 DiskANN。
  • 全文搜索:Azure Cosmos DB for MongoDB (vCore)使用 $text 运算符进行全文搜索。

然后,将矢量搜索和全文搜索的结果组合在一起,以返回最终搜索结果,受益于这两种搜索方法的优势:

  • 增强相关性:通过将语义理解与关键字匹配相结合,混合搜索可以为各种查询提供更相关的结果。
  • 改进准确度:RRF 函数可确保确定这两种搜索方法中最相关结果的优先级。
  • 多功能性:适用于各种用例,包括建议系统、语义搜索和个性化内容发现。
  1. 创建一个集合来存储数据,包括文本内容和矢量嵌入。
  2. 使用cosmosSearch运算符在矢量嵌入字段上创建矢量索引
  3. 使用 $text 类型的标准索引创建命令在文本字段中创建全文索引。
  4. 将聚合管道与 $search 运算符(用于矢量搜索)和 $text 运算符(用于全文搜索)配合使用,然后执行步骤来实现倒数排名融合,以使用 $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]字段执行矢量相似性搜索,返回前五个最相似的文档(k: 5)。 然后,阶段 $group 将所有矢量搜索结果分组到一个包含名为 vectorResults数组的单个文档中。 在此之后, $unwind 阶段将 vectorResults 析构数组,为每个结果创建一个单独的文档并添加其排名(vectorRank)。 后续 $addFields 阶段根据每个矢量搜索结果的排名计算倒数排名融合 (RRF) 分数。 然后,阶段$project会从矢量搜索结果中选择_idtitle以及计算得到的vs_score

进入文本搜索阶段,阶段 $unionWith 将矢量搜索管道的结果与单独的全文搜索管道的结果组合在一起。 在全文搜索阶段, $match 具有 $text 运算符的阶段对文本字段中的“cat”一词执行全文搜索。 $addFields阶段检索由$text运算符分配的相关性分数(textScore)。 与矢量搜索结果类似, $group 阶段将所有全文搜索结果分组,阶段 $unwind 将解 textResults 构数组,并添加排名(textRank)。 此处使用了不同的惩罚 (10),可以对其进行优化。 $project阶段从全文搜索结果中选择_idtitlefts_score。 合并结果后,$group阶段按照title对文档进行分组。

最后,$project阶段通过对每个文档取其矢量 RRF 分数 vs_score和全文 RRF 分数 fts_score的最大值来计算finalScore$ifNull 处理文档可能仅存在于其中一个搜索结果中的情况。

局限性

  • Azure Cosmos DB for MongoDB 的全文搜索目前不支持 BM25 排名。
  • 目前,没有用于直接执行混合搜索的单个专用命令。 需要使用聚合管道构造混合搜索查询,如上面的示例所示。

后续步骤