定义
语法
$unionWith 阶段使用以下语法:
{ $unionWith: { coll: "<collection>", pipeline: [ <stage1>, ... ] } }要包含指定集合中的所有文档而不进行任何处理,您可以使用简化的形式:
{ $unionWith: "<collection>" } // Include all documents from the specified collection$unionWith 阶段采用包含以下字段的文档:
字段 | 必要性 | 说明 |
|---|---|---|
如果省略 | 您希望将其管道结果包含在结果集中的集合或视图。 如果省略 | |
如果省略 | 应用于输入文档的聚合管道。
管道不能包括 |
$unionWith操作对应于如下 SQL 语句:
SELECT *FROM Collection1WHERE ...UNION ALLSELECT *FROM Collection2WHERE ...Considerations
重复结果
前一阶段和 $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搜索支持
从MongoDB 6.0 开始,您可以在 $unionWith管道中指定MongoDB搜索 $search 或 $searchMeta 阶段来搜索Atlas 集群上的集合。$search 或 $searchMeta 阶段必须是 $unionWith管道内的第一个阶段。
[{ "$unionWith": { "coll": <collection-name>, "pipeline": [{ "$search": { "<operator>": { <operator-specification> } }, ... }] }}][{ "$unionWith": { "coll": <collection-name>, "pipeline": [{ "$searchMeta": { "<collector>": { <collector-specification> } }, ... }] }}]要查看 $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 管道不能包含 |
示例
本页上的示例使用来自 sample_mflix 数据集的数据。有关如何将此数据集加载到您的自管理 MongoDB 部署中的详细信息,请参阅 加载示例数据集。如果您对示例数据库进行了任何修改,您可能需要删除并重新创建数据库,才能运行此页面上的示例。
从电影数据联合中创建电影报告
以下示例使用 $unionWith 阶段合并数据,并从 movies 集合中返回结果。
报告 1:按类别和年份列出的所有电影
以下聚合创建了一份按类别列出电影的电影报告。该管道使用 $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阶段。
报告 2:按流派划分的聚合运行时
以下聚合创建了一份电影报告,其中列出了每个类型的总运行时间。该管道使用 $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集合中的文档检索到管道中。$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 }]本页上的C#示例使用Atlas示例数据集中的 sample_mflix数据库。要学习;了解如何创建免费的MongoDB Atlas 群集并加载示例数据集,请参阅MongoDB .NET/ C#驱动程序文档中的入门。
以下 Movie 类对 sample_mflix.movies 集合中的文档进行建模:
[BsonIgnoreExtraElements]public class Movie{ [BsonId] public ObjectId Id { get; set; } [BsonElement("title")] public string Title { get; set; } = null!; [BsonElement("year")] public int? Year { get; set; } [BsonElement("runtime")] public int? Runtime { get; set; } [BsonElement("rated")] public string? Rated { get; set; } [BsonElement("metacritic")] public int Metacritic { get; set; } [BsonElement("plot")] public string? Plot { get; set; } [BsonElement("type")] public string? Type { get; set; } [BsonElement("cast")] public string[]? Cast { get; set; } [BsonElement("directors")] public string[]? Directors { get; set; } [BsonElement("writers")] public string[]? Writers { get; set; } [BsonElement("imdb")] public ImdbData? Imdb { get; set; }}要使用MongoDB .NET/C# 驱动程序将 $unionWith 阶段添加到聚合管道,请对 PipelineDefinition 对象调用 UnionWith() 方法。
以下示例创建了一个管道阶段,用于将 sample_mflix.movies 集合中 Metacritic 分数为 100 的电影与符合相同条件的电影合并在一起:
var pipeline = new EmptyPipelineDefinition<Movie>() .Match(Builders<Movie>.Filter.Eq(m => m.Metacritic, 100)) .UnionWith( withCollection: _movies, withPipeline: new EmptyPipelineDefinition<Movie>() .Match(Builders<Movie>.Filter.Eq(m => m.Metacritic, 100)));{ "metacritic" : 100, "title" : "Best Kept Secret" }{ "metacritic" : 100, "title" : "Best Kept Secret" }{ "metacritic" : 100, "title" : "Boyhood" }{ "metacritic" : 100, "title" : "Boyhood" }{ "metacritic" : 100, "title" : "Fanny and Alexander" }{ "metacritic" : 100, "title" : "Fanny and Alexander" }{ "metacritic" : 100, "title" : "Lawrence of Arabia" }{ "metacritic" : 100, "title" : "Lawrence of Arabia" }{ "metacritic" : 100, "title" : "The Conformist" }{ "metacritic" : 100, "title" : "The Conformist" }{ "metacritic" : 100, "title" : "The Godfather" }{ "metacritic" : 100, "title" : "The Godfather" }{ "metacritic" : 100, "title" : "The Leopard" }{ "metacritic" : 100, "title" : "The Leopard" }{ "metacritic" : 100, "title" : "The Wizard of Oz" }{ "metacritic" : 100, "title" : "The Wizard of Oz" }本页上的 Node.js 示例使用 Atlas 示例数据集中的 sample_mflix数据库。要学习如何创建免费的MongoDB Atlas 集群并加载示例数据集,请参阅MongoDB Node.js驱动程序文档中的入门。
要使用MongoDB Node.js驱动程序将 $unionWith 阶段添加到聚合管道,请在管道对象中使用 $unionWith操作符。
以下示例创建了一个管道阶段,它将 sample_mflix.movies集合中的传入文档与 sample_mflix.movies集合中的 movie 文档合并。然后,该示例运行聚合管道:
const db = client.db("sample_mflix");const collection = db.collection("movies");
const pipeline = [{ $unionWith: { coll: "Movies" } }];
const cursor = collection.aggregate(pipeline);return cursor;