对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。

$rankFusion(聚合)

重要

$rankFusion 仅适用于使用MongoDB 8.0 或更高版本的部署。

$rankFusion

$rankFusion 首先独立执行所有输入管道,然后去重并将输入管道结果组合成最终的排名结果设立。

$rankFusion 根据输入文档在其输入管道中出现的排名以及管道权重,输出一设立经过排名的文档。此阶段使用倒数排名融合算法对输入管道的组合结果进行排名。

使用 $rankFusion 根据多个条件在单个集合中搜索文档,并检索了所有指定条件的最终排名结果设立。

该阶段采用以下语法:

{ $rankFusion: { input: { pipelines: { <myPipeline1>: <expression>, <myPipeline2>: <expression>, ... } }, combination: { weights: { <myPipeline1>: <numeric expression>, <myPipeline2>: <numeric expression>, ... } }, scoreDetails: <bool> } }

$rankFusion 采用以下字段:

字段
类型
说明

input

对象

定义 $rankFusion 排名的输入。

input.
pipelines

对象

包含管道名称到定义该管道的聚合阶段的映射。input.pipelines 必须至少包含一个管道。所有管道必须对同一个集合进行操作,并且必须具有唯一的名称。

有关输入管道限制的更多信息,请参阅输入管道和输入管道名称。

combination

对象

可选。定义如何合并 input管道结果。

combination.
weights

对象

可选。包含从 input管道名称到其相对于其他管道的权重的映射。每个权重值必须是非负数(整数或小数)。

如果未指定权重,默认值为 1。

scoreDetails

布尔

默认值为 false。指定 $rankFusion 是否为每个输出文档计算并填充 $scoreDetails 元数据字段。有关此字段的更多信息,请参阅 scoreDetails。

您只能将 $rankFusion 与单个集合一起使用。您不能在数据库范围内使用此聚合阶段。

$rankFusion 对最终输出中多个输入管道的结果去重。每个唯一的输入文档在 $rankFusion 输出中最多出现一次,无论该文档在输入管道输出中出现多少次。

每个 input管道必须既是选择管道又是排名管道。

选择管道从集合中检索一设立文档,并且在检索后不执行任何修改。$rankFusion 比较不同输入管道中的文档,这要求所有输入管道输出相同的未经修改的文档。

注意

如果要修改使用 $rankFusion搜索的文档,请在 $rankFusion 阶段之后执行这些修改。

选择管道必须仅包含以下阶段:

类型
阶段(Stages)

搜索阶段

对阶段进行排序

分页阶段

排名管道对文档进行排序或排序。$rankFusion 使用排名管道结果的顺序来影响输出排名。排名管道必须满足以下条件之一:

input 中的管道名称必须符合以下限制:

  • 不得为空字符串

  • 不得以 $

  • 不得在字符串中的任何位置包含 ASCII 空字符分隔符 \0

  • 不得包含 .

$rankFusion 根据倒数排名融合 (RRF) 公式对结果进行排序。此阶段将每个文档的 RRF 分数放入输出结果的 score元数据字段中。RRF 公式结合以下因素对文档进行排名:

  • 文档在输入管道结果中的放置

  • 文档在不同输入管道中出现的次数

  • 输入管道的 weights。

示例,如果某一文档在多个管道结果集中排名较高,则该文档的 RRF 分数将高于该文档在某些输入管道中排名相同但不存在(或排名较低)的情况。在其他管道中

倒数排名融合 (RRF) 公式等效于以下代数运算:

注意

在此公式中,60 是MongoDB确定的敏感度参数。

下表包含 RRF 公式使用的变量:

变量
说明

D

整个操作的结果文档设立。

d

正在计算 RRF 分数的文档。

R

d 出现在的输入管道的排名设立。

r(d)

文档d 在此输入管道中的排名。

w

d 出现在的输入管道的权重。

总和中的每术语代表文档d 在 input 管道之一中的出现情况。d 的 RRF 总分数是 d 出现的所有输入管道中每个词的总和。

考虑具有一个 $search 和一个 $vectorSearch 输入管道的 $rankFusion管道阶段。

所有输入管道均输出相同的 3 文档:Document1、Document2 和 Document3。

$search管道按以下顺序对文档进行排名:

  1. Document3

  2. Document2

  3. Document1

$vectorSearch管道按以下顺序对文档进行排名:

  1. Document1

  2. Document2

  3. Document3.

rankFusion 通过以下操作计算 Document1 的 RRF 分数:

RRFscore(Document1) = 1/(60 + search_rank_of_Document1) + (1/(60 + vectorSearch_rank_of_Document1))RRFscore(Document1) = 1/63 + 1/61RRFscore(Document1) = 0.0322664585

Document1 的 score 元元数据字段为 0.0322664585。

如果将 scoreDetails设立为 true,$rankFusion 则会为每个文档创建一个 scoreDetails 元元数据字段。scoreDetails字段包含有关最终排名的信息。

注意

当您将 scoreDetails设立为 true 时,$rankFusion 会为每个文档设置 scoreDetails 元元数据字段,但不会自动输出 scoreDetails 元字段。

要查看 scoreDetails元数据字段,您必须:

  • 在 $rankFusion 之后使用 $project 阶段项目scoreDetails字段

  • 在 $rankFusion 之后使用 $addFields 阶段将 scoreDetails字段添加到管道输出

scoreDetails字段包含以下子字段:

字段
说明

value

此文档的 RRF 分数的数值。

description

$rankFusion 如何计算 RRF 分数的说明。

details

一个大量,其中每个大量条目都包含有关输出此文档的输入管道的信息。

details字段中的每个大量条目都包含以下子字段:

字段
说明

inputPipelineName

输出此文档的输入管道的名称。

rank

此文档在输入管道中的排名。如果其他管道阶段输出中返回的文档不存在于此管道阶段的输出中,则该管道阶段输出中的排名为 N/A。

weight

输入管道的权重。

value

可选。如果输入管道输出此文档的 { $meta: 'score' },则 value 包含 { $meta: 'score' }。

description

可选。如果输入管道输出 description字段作为此文档的 scoreDetails 的一部分,则 details.description 包含该字段值。

details

输入管道的 scoreDetails字段。如果输入管道未输出 scoreDetails字段,则该字段为空大量。

警告

MongoDB不保证 scoreDetails 的任何特定输出格式。

示例,以下代码块显示具有 $search、$vectorSearch 和 $match 输入管道的 $rankFusion 操作的 scoreDetails字段:

{ value: 0.030621785881252923, description: "value output by reciprocal rank fusion algorithm, computed as sum of weight * (1 / (60 + rank)) across input pipelines from which this document is output, from:" details: [ { inputPipelineName: 'search', rank: 2, weight: 1, value: 0.3876491287, description: "sum of:", details: [... omitted for brevity in this example ...] }, { inputPipelineName: 'vector', rank: 9, weight: 3, value: 0.7793490886688232, details: [ ] }, { inputPipelineName: 'match', rank: 10, weight: 1, details: [] } ] }

MongoDB将 $rankFusion 操作转换为一设立现有的聚合阶段,这些阶段在查询执行之前结合起来计算输出结果。$rankFusion 操作的“解释结果”显示了 $rankFusion 用于构成最终结果的根本的聚合阶段的完整执行情况。

此示例使用具有嵌入和文本字段的集合。在集合上创建 search 和 vectorSearch 类型索引。

以下索引定义自动为集合中的所有动态可索引字段编制索引,以便对索引字段运行$search 查询。

搜索索引

db.embedded_movies.createSearchIndex( "search_index", { mappings: { dynamic: true } })

以下索引定义使用集合中的嵌入对该字段进行索引,以便对该字段运行$vectorSearch 查询。

vectorSearch 索引

db.embedded_movies.createSearchIndex( "vector_index", "vectorSearch", { "fields": [ { "type": "vector", "path": "<FIELD_NAME>", "numDimensions": <NUMBER_OF_DIMENSIONS>, "similarity": "dotProduct" } ] });

以下聚合管道将 $rankFusion 与以下输入管道结合使用:

管道
返回的文档数量
说明

searchOne

20

在索引为 vector 类型的字段上,针对指定为嵌入的术语运行向量搜索。该查询最多考虑 500 个最近邻,但将结果限制为 20 个文档。

searchTwo

20

对同一术语运行全文搜索,并将结果限制为 20 个文档。

db.embedded_movies.aggregate( [ { $rankFusion: { input: { pipelines: { searchOne: [ { "$vectorSearch": { "index": "<INDEX_NAME>", "path": "<FIELD_NAME>", "queryVector": <QUERY_EMBEDDINGS>, "numCandidates": 500, "limit": 20 } } ], searchTwo: [ { "$search": { "index": "<INDEX_NAME>", "text": { "query": "<QUERY_TERM>", "path": "<FIELD_NAME>" } } }, { "$limit": 20 } ], } } } }, { $limit: 20 }] )

此操作执行以下操作:

  • 执行 input 管道

  • 合并返回的结果

  • 输出前 20 个文档,即 $rankFusion管道中排名前 20 的结果

给本页内容打分