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

$unionWith(聚合阶段)

$unionWith

在版本8.0中进行了更改。

将两个聚合合并为一个结果集。$unionWith 将合并的结果集(包括重复项)输出到下一阶段。

未指定合并结果集文档的输出顺序。

$unionWith 阶段使用以下语法:

{ $unionWith: { coll: "<collection>", pipeline: [ <stage1>, ... ] } }

要包含指定集合中的所有文档而不进行任何处理,您可以使用简化的形式:

{ $unionWith: "<collection>" } // Include all documents from the specified collection

$unionWith 阶段采用包含以下字段的文档:

字段
必要性
说明

如果省略 pipeline,则为必需。否则为可选。

您希望将其管道结果包含在结果集中的集合或视图。

如果省略 coll 字段,则必须指定第一阶段为 $documents 的 pipeline 字段。

如果省略 coll,则为必需。否则为可选。

应用于输入文档的聚合管道。

  • 如果指定 coll,则管道适用于 coll 中的文档。

  • 如果省略 coll,则管道适用于管道 $documents 阶段的文档。有关示例,请参见创建具有特定文档的联合。

管道不能包括 $out 和 $merge 阶段。从 v6.0 开始,pipeline 可以包含 MongoDB Search $search 阶段作为管道内的第一阶段。要了解更多信息,请参阅 MongoDB Search 支持。

$unionWith操作对应于如下 SQL 语句:

SELECT *FROM Collection1WHERE ...UNION ALLSELECT *FROM Collection2WHERE ...

前一阶段和 $unionWith 阶段的合并结果可能包括重复结果。

示例,以下聚合组合了来自 movies 集合的两个查询的 title 字段投影结果。结果集包含重复项:

db.movies.aggregate( [ { $match: { runtime: { $gt: 1000 } } }, { $project: { title: 1, _id: 0 } }, { $unionWith: { coll: "movies", pipeline: [ { $match: { runtime: { $gt: 1000 } } }, { $project: { title: 1, _id: 0 } } ] } }] )
[ { title: 'Centennial' }, { title: 'Baseball' }, { title: 'Centennial' }, { title: 'Baseball' }]

要删除重复项,可以包括一个 $group 阶段,按照 title 字段进行分组。结果集不再包含重复项:

db.movies.aggregate( [ { $match: { runtime: { $gt: 1000 } } }, { $project: { title: 1, _id: 0 } }, { $unionWith: { coll: "movies", pipeline: [ { $match: { runtime: { $gt: 1000 } } }, { $project: { title: 1, _id: 0 } } ] } }, { $group: { _id: "$title" } }, { $sort: { _id: 1 } }] )
[ { _id: 'Baseball' }, { _id: 'Centennial' }]

如果 db.collection.aggregate() 包含 collation 文档,则操作使用该排序规则,并忽略任何其他排序规则。

如果db.collection.aggregate()不包含collation文档,则db.collection.aggregate()方法将使用运行db.collection.aggregate()的顶级集合/视图的排序规则:

  • 如果 $unionWith coll 是一个集合,它的排序规则将被忽略。

  • 如果 $unionWith coll 是一个视图,则它必须与顶层集合/视图具有一致的排序规则。否则,操作将出错。

从MongoDB 6.0 开始,您可以在 $unionWith管道中指定MongoDB搜索 $search 或 $searchMeta 阶段来搜索Atlas 集群上的集合。$search 或 $searchMeta 阶段必须是 $unionWith管道内的第一个阶段。

要查看 $unionWith 和 $search 的示例,请参阅 MongoDB Search 教程 使用 $unionWith 运行MongoDB Search $ 搜索查询。

从 MongoDB 8.0 开始,会验证 $lookup 和 $unionWith 内子管道中的命名空间,以确保正确使用 from 和 coll 字段:

  • 对于 $lookup,如果您使用的子管道具有不需要指定集合的阶段,请省略 from 字段。例如,$documents 阶段。

  • 同样,对于 $unionWith,省略 coll 字段。

保持不变的行为:

  • 对于以集合阶段开头的 $lookup,例如 $match 或 $collStats 子管道,必须包含 from 字段并指定集合。

  • 同样,对于 $unionWith,包含 coll 字段并指定集合。

限制
说明

聚合管道不能在事务中使用 $unionWith。

$unionWith 管道不能包含 $out 阶段。

$unionWith 管道不能包含 $merge 阶段。

本页上的示例使用来自 sample_mflix 数据集的数据。有关如何将此数据集加载到您的自管理 MongoDB 部署中的详细信息,请参阅 加载示例数据集。如果您对示例数据库进行了任何修改,您可能需要删除并重新创建数据库,才能运行此页面上的示例。

以下示例使用 $unionWith 阶段合并数据,并从 movies 集合中返回结果。

以下聚合创建了一份按类别列出电影的电影报告。该管道使用 $unionWith 来合并 movies 集合中的文档:

db.movies.aggregate( [ { $match: { year: { $lt: 1910 } } }, { $set: { category: "Early Cinema" } }, { $unionWith: { coll: "movies", pipeline: [ { $match: { runtime: { $gt: 1000 } } }, { $set: { category: "Long Runtime" } } ] } }, { $project: { title: 1, year: 1, category: 1, _id: 0 } }, { $sort: { category: 1, year: 1, title: 1 } }] )
[ { title: 'The Kiss', year: 1896, category: 'Early Cinema' }, { title: 'The Kiss', year: 1896, category: 'Early Cinema' }, { title: 'The Great Train Robbery', year: 1903, category: 'Early Cinema' }, { title: 'A Corner in Wheat', year: 1909, category: 'Early Cinema' }, { title: 'Centennial', year: 1978, category: 'Long Runtime' }, { title: 'Baseball', year: 1994, category: 'Long Runtime' }]

具体来说,聚合管道使用:

  • 一个用于选择 1910 之前发布的电影的 $match 阶段。

  • 一个 $set 阶段,用于添加一个值为 Early Cinema 的 category 字段。

  • 一个 $unionWith 阶段,用于合并来自 movies 集合的文档,过滤器出 runtime 大于 1000 且标签为 Long Runtime 类别的电影。

  • 一个 $project 阶段,仅返回 title、year 和 category 字段。

  • 按category、year和title排序的$sort阶段。

以下聚合创建了一份电影报告,其中列出了每个类型的总运行时间。该管道使用 $unionWith 来合并来自 movies 集合的文档:

db.movies.aggregate( [ { $match: { year: { $lt: 1910 } } }, { $unionWith: { coll: "movies", pipeline: [ { $match: { runtime: { $gt: 1000 } } } ] } }, { $group: { _id: "$genres", totalRuntime: { $sum: "$runtime" } } }, { $sort: { totalRuntime: -1 } }] )
[ { _id: [ 'Action', 'Adventure', 'Drama' ], totalRuntime: 1256 }, { _id: [ 'Documentary', 'History', 'Sport' ], totalRuntime: 1140 }, { _id: [ 'Short', 'Drama' ], totalRuntime: 14 }, { _id: [ 'Short', 'Western' ], totalRuntime: 11 }, { _id: [ 'Short', 'Romance' ], totalRuntime: 2 }]
  • $match 和 $unionWith 阶段将 movies 集合中的文档检索到管道中。

  • $group 阶段按 genres 字段进行分组,并使用 $sum 计算每个 genres 值的总 runtime。

  • $sort阶段按降序totalRuntime 排列文档。

您可以使用 $unionWith 与 pipeline 字段中指定的文档执行联合。在 pipeline 字段中指定 $documents 阶段时,您可以与未存储在单独集合中的文档执行联合。

以下 $unionWith 操作将与 pipeline $documents 字段中指定的文档联合:

db.movies.aggregate( [ { $match: { runtime: { $gt: 1000 } } }, { $project: { title: 1, year: 1, _id: 0 } }, { $unionWith: { pipeline: [ { $documents: [ { title: "Movie A", year: 2000 }, { title: "Movie B", year: 2001 } ] } ] } }] )
[ { title: 'Centennial', year: 1978 }, { title: 'Baseball', year: 1994 }, { title: 'Movie A', year: 2000 }, { title: 'Movie B', year: 2001 }]