Definition定义
$unionWithChanged in version 8.0.在版本8.0中更改。Combines two aggregations into a single result set.将两个聚合合并到一个结果集中。$unionWithoutputs the combined result set (including duplicates) to the next stage.$unionWith将组合结果集(包括重复项)输出到下一阶段。The order in which the combined result set documents are output is unspecified.未指定组合结果集文档的输出顺序。
Syntax语法
The $unionWith stage has the following syntax:$unionWith阶段具有以下语法:
{ $unionWith: { coll: "<collection>", pipeline: [ <stage1>, ... ] } }
To include all documents from the specified collection without any processing, you can use the simplified form:要包含指定集合中的所有文档而不进行任何处理,您可以使用简化表格:
{ $unionWith: "<collection>" } // Include all documents from the specified collection包括指定集合中的所有文档
The $unionWith stage takes a document with the following fields:$unionWith阶段接收具有以下字段的文档:
coll | pipeline is omitted. Otherwise optional.pipeline,则需要。否则可选。 |
|
pipeline | coll is omitted. Otherwise optional.coll,则为必填项。否则可选。 |
|
The $unionWith operation would correspond to the following SQL statement:$unionWith操作将对应于以下SQL语句:
SELECT *
FROM Collection1
WHERE ...
UNION ALL
SELECT *
FROM Collection2
WHERE ...Considerations注意事项
Duplicate Results重复结果
The combined results from the previous stage and the 前一阶段和$unionWith stage can include duplicates.$unionWith阶段的组合结果可能包含重复项。
For example, create a 例如,创建suppliers collection and a warehouses collection:suppliers(供应商)集合和warehouses(仓库)集合:
db.suppliers.insertMany([
{ _id: 1, supplier: "Aardvark and Sons", state: "Texas" },
{ _id: 2, supplier: "Bears Run Amok.", state: "Colorado"},
{ _id: 3, supplier: "Squid Mark Inc. ", state: "Rhode Island" },
])
db.warehouses.insertMany([
{ _id: 1, warehouse: "A", region: "West", state: "California" },
{ _id: 2, warehouse: "B", region: "Central", state: "Colorado"},
{ _id: 3, warehouse: "C", region: "East", state: "Florida" },
])
The following aggregation combines the 以下聚合组合了来自state field projection results from the suppliers and warehouse collections.suppliers和warehouse集合的state字段预测结果。
db.suppliers.aggregate([
{ $project: { state: 1, _id: 0 } },
{ $unionWith: { coll: "warehouses", pipeline: [ { $project: { state: 1, _id: 0 } } ]} }
])
The result set contains duplicates:结果集包含重复项:
{ "state" : "Texas" }
{ "state" : "Colorado" }
{ "state" : "Rhode Island" }
{ "state" : "California" }
{ "state" : "Colorado" }
{ "state" : "Florida" }
To remove the duplicates, you can include a 要删除重复项,您可以包含一个$group stage to group by the state field:$group阶段,按state字段分组:
db.suppliers.aggregate([
{ $project: { state: 1, _id: 0 } },
{ $unionWith: { coll: "warehouses", pipeline: [ { $project: { state: 1, _id: 0 } } ]} },
{ $group: { _id: "$state" } }
])
The result set no longer contains duplicates:结果集不再包含重复项:
{ "_id" : "California" }
{ "_id" : "Texas" }
{ "_id" : "Florida" }
{ "_id" : "Colorado" }
{ "_id" : "Rhode Island" }$unionWith a Sharded Collection分片集合
If the 如果$unionWith stage is part of the pipeline, the $unionWith coll cannot be sharded. For example, in the following aggregation operation, the inventory_q1 collection cannot be sharded:$unionWith阶段是管道的一部分,则$unionWith coll不能被分片。例如,在以下聚合操作中,无法对investory_q1集合进行分片:
db.suppliers.aggregate([
{
$lookup: {
from: "warehouses",
let: { order_item: "$item", order_qty: "$ordered" },
pipeline: [
...
{ $unionWith: { coll: "inventory_q1", pipeline: [ ... ] } },
...
],
as: "stockdata"
}
}
])Collation排序规则
If the 如果db.collection.aggregate() includes a collation document, that collation is used for the operation, ignoring any other collations.db.collection.aggregate()包含collation文档,则该排序规则将用于操作,忽略任何其他排序规则。
If the 如果db.collection.aggregate() does not include a collation document, the db.collection.aggregate() method uses the collation for the top-level collection/view on which the db.collection.aggregate() is run:db.collection.aggregate()不包含collation文档,则db.collection.aggregate()方法将使用运行db.collection.aggregate()的顶级集合/视图的排序规则:
If the $unionWith coll is a collection, its collation is ignored.如果$unionWithcoll一个集合,则忽略其排序规则。If the $unionWith coll is a view, then its collation must match that of the top-level collection/view.如果$unionWithcoll是视图,则其排序规则必须与顶级集合/视图的排序规则匹配。Otherwise, the operation errors.否则,操作错误。
MongoDB Search SupportMongoDB搜索支持
Starting in MongoDB 6.0, you can specify the MongoDB Search 从MongoDB 6.0开始,您可以在$search or $searchMeta stage in the $unionWith pipeline to search collections on the Atlas cluster. $unionWith管道中指定MongoDB Search$search或$searchMeta阶段,以搜索Atlas集群上的集合。The $search or the $searchMeta stage must be the first stage inside the $unionWith pipeline.$search或$searchMeta阶段必须是$unionWith管道中的第一阶段。
$search
[{
"$unionWith": {
"coll": <collection-name>,
"pipeline": [{
"$search": {
"<operator>": {
<operator-specification>
}
},
...
}]
}
}]$searchMeta
[{
"$unionWith": {
"coll": <collection-name>,
"pipeline": [{
"$searchMeta": {
"<collector>": {
<collector-specification>
}
},
...
}]
}
}]To see an example of 要查看$unionWith with $search, see the MongoDB Search tutorial Run a MongoDB Search $search Query Using $unionWith.$unionWith和$search的示例,请参阅MongoDB搜索教程使用$unionWith运行MongoDB搜索$search查询。
Restrictions限制
transactions | $unionWith inside transactions.$unionWith。 |
$unionWith stage is part of the pipeline, the $unionWith coll cannot be sharded.$unionWith阶段是管道的一部分,则$unionWith coll不能被分片。 | |
$out | $out stage.$unionWith pipeline不能包含$out阶段。 |
$merge | $merge stage.$unionWith pipeline不能包含$merge阶段。 |
Examples示例
MongoDB Shell
Create Sales Reports from the Union of Yearly Data Collections从年度数据集合联盟创建销售报告
The following examples use the 以下示例使用$unionWith stage to combine data and return results from multiple collections. In these examples, each collection contains a year of sales data.$unionWith阶段组合数据并返回多个集合的结果。在这些示例中,每个集合都包含一年的销售数据。
Populate Sample Data填充样本数据
Create a使用以下文档创建sales_2017collection with the following documents:sales_2017集合:db.sales_2017.insertMany( [
{ store: "General Store", item: "Chocolates", quantity: 150 },
{ store: "ShopMart", item: "Chocolates", quantity: 50 },
{ store: "General Store", item: "Cookies", quantity: 100 },
{ store: "ShopMart", item: "Cookies", quantity: 120 },
{ store: "General Store", item: "Pie", quantity: 10 },
{ store: "ShopMart", item: "Pie", quantity: 5 }
] )Create a使用以下文档创建sales_2018collection with the following documents:sales_2018集合:db.sales_2018.insertMany( [
{ store: "General Store", item: "Cheese", quantity: 30 },
{ store: "ShopMart", item: "Cheese", quantity: 50 },
{ store: "General Store", item: "Chocolates", quantity: 125 },
{ store: "ShopMart", item: "Chocolates", quantity: 150 },
{ store: "General Store", item: "Cookies", quantity: 200 },
{ store: "ShopMart", item: "Cookies", quantity: 100 },
{ store: "ShopMart", item: "Nuts", quantity: 100 },
{ store: "General Store", item: "Pie", quantity: 30 },
{ store: "ShopMart", item: "Pie", quantity: 25 }
] )Create a使用以下文档创建sales_2019collection with the following documents:sales_2019集合:db.sales_2019.insertMany( [
{ store: "General Store", item: "Cheese", quantity: 50 },
{ store: "ShopMart", item: "Cheese", quantity: 20 },
{ store: "General Store", item: "Chocolates", quantity: 125 },
{ store: "ShopMart", item: "Chocolates", quantity: 150 },
{ store: "General Store", item: "Cookies", quantity: 200 },
{ store: "ShopMart", item: "Cookies", quantity: 100 },
{ store: "General Store", item: "Nuts", quantity: 80 },
{ store: "ShopMart", item: "Nuts", quantity: 30 },
{ store: "General Store", item: "Pie", quantity: 50 },
{ store: "ShopMart", item: "Pie", quantity: 75 }
] )Create a使用以下文档创建sales_2020collection with the following documents:sales_2020集合:db.sales_2020.insertMany( [
{ store: "General Store", item: "Cheese", quantity: 100, },
{ store: "ShopMart", item: "Cheese", quantity: 100},
{ store: "General Store", item: "Chocolates", quantity: 200 },
{ store: "ShopMart", item: "Chocolates", quantity: 300 },
{ store: "General Store", item: "Cookies", quantity: 500 },
{ store: "ShopMart", item: "Cookies", quantity: 400 },
{ store: "General Store", item: "Nuts", quantity: 100 },
{ store: "ShopMart", item: "Nuts", quantity: 200 },
{ store: "General Store", item: "Pie", quantity: 100 },
{ store: "ShopMart", item: "Pie", quantity: 100 }
] )
Report 1: All Sales by Year and Stores and Items报告1:按年份、门店和商品列出的所有销售额
The following aggregation creates a yearly sales report that lists all sales by quarter and stores. The pipeline uses 以下汇总创建了一份年度销售报告,其中按季度和门店列出了所有销售额。该管道使用$unionWith to combine documents from all four collections:$unionWith组合来自所有四个集合的文档:
db.sales_2017.aggregate( [
{ $set: { _id: "2017" } },
{ $unionWith: { coll: "sales_2018", pipeline: [ { $set: { _id: "2018" } } ] } },
{ $unionWith: { coll: "sales_2019", pipeline: [ { $set: { _id: "2019" } } ] } },
{ $unionWith: { coll: "sales_2020", pipeline: [ { $set: { _id: "2020" } } ] } },
{ $sort: { _id: 1, store: 1, item: 1 } }
] )
Specifically, the aggregation pipeline uses:具体来说,聚合管道使用:
A一个$setstage to update the_idfield to contain the year.$set阶段,用于更新_id字段以包含年份。A sequence of一系列$unionWithstages to combine all documents from the four collections, each also using the$setstage on its documents.$unionWith阶段,用于组合四个集合中的所有文档,每个集合也在其文档上使用$set阶段。A$sortstage to sort by the_id(the year), thestore, anditem.$sort阶段,按_id(年份)、store和item进行排序。
Pipeline output:管道输出:
{ "_id" : "2017", "store" : "General Store", "item" : "Chocolates", "quantity" : 150 }
{ "_id" : "2017", "store" : "General Store", "item" : "Cookies", "quantity" : 100 }
{ "_id" : "2017", "store" : "General Store", "item" : "Pie", "quantity" : 10 }
{ "_id" : "2017", "store" : "ShopMart", "item" : "Chocolates", "quantity" : 50 }
{ "_id" : "2017", "store" : "ShopMart", "item" : "Cookies", "quantity" : 120 }
{ "_id" : "2017", "store" : "ShopMart", "item" : "Pie", "quantity" : 5 }
{ "_id" : "2018", "store" : "General Store", "item" : "Cheese", "quantity" : 30 }
{ "_id" : "2018", "store" : "General Store", "item" : "Chocolates", "quantity" : 125 }
{ "_id" : "2018", "store" : "General Store", "item" : "Cookies", "quantity" : 200 }
{ "_id" : "2018", "store" : "General Store", "item" : "Pie", "quantity" : 30 }
{ "_id" : "2018", "store" : "ShopMart", "item" : "Cheese", "quantity" : 50 }
{ "_id" : "2018", "store" : "ShopMart", "item" : "Chocolates", "quantity" : 150 }
{ "_id" : "2018", "store" : "ShopMart", "item" : "Cookies", "quantity" : 100 }
{ "_id" : "2018", "store" : "ShopMart", "item" : "Nuts", "quantity" : 100 }
{ "_id" : "2018", "store" : "ShopMart", "item" : "Pie", "quantity" : 25 }
{ "_id" : "2019", "store" : "General Store", "item" : "Cheese", "quantity" : 50 }
{ "_id" : "2019", "store" : "General Store", "item" : "Chocolates", "quantity" : 125 }
{ "_id" : "2019", "store" : "General Store", "item" : "Cookies", "quantity" : 200 }
{ "_id" : "2019", "store" : "General Store", "item" : "Nuts", "quantity" : 80 }
{ "_id" : "2019", "store" : "General Store", "item" : "Pie", "quantity" : 50 }
{ "_id" : "2019", "store" : "ShopMart", "item" : "Cheese", "quantity" : 20 }
{ "_id" : "2019", "store" : "ShopMart", "item" : "Chocolates", "quantity" : 150 }
{ "_id" : "2019", "store" : "ShopMart", "item" : "Cookies", "quantity" : 100 }
{ "_id" : "2019", "store" : "ShopMart", "item" : "Nuts", "quantity" : 30 }
{ "_id" : "2019", "store" : "ShopMart", "item" : "Pie", "quantity" : 75 }
{ "_id" : "2020", "store" : "General Store", "item" : "Cheese", "quantity" : 100 }
{ "_id" : "2020", "store" : "General Store", "item" : "Chocolates", "quantity" : 200 }
{ "_id" : "2020", "store" : "General Store", "item" : "Cookies", "quantity" : 500 }
{ "_id" : "2020", "store" : "General Store", "item" : "Nuts", "quantity" : 100 }
{ "_id" : "2020", "store" : "General Store", "item" : "Pie", "quantity" : 100 }
{ "_id" : "2020", "store" : "ShopMart", "item" : "Cheese", "quantity" : 100 }
{ "_id" : "2020", "store" : "ShopMart", "item" : "Chocolates", "quantity" : 300 }
{ "_id" : "2020", "store" : "ShopMart", "item" : "Cookies", "quantity" : 400 }
{ "_id" : "2020", "store" : "ShopMart", "item" : "Nuts", "quantity" : 200 }
{ "_id" : "2020", "store" : "ShopMart", "item" : "Pie", "quantity" : 100 }Report 2: Aggregated Sales by Items报告2:按项目汇总的销售额
The following aggregation creates a sales report that lists the sales quantity per item. The pipeline uses 以下聚合创建了一个销售报告,其中列出了每个项目的销售数量。该管道使用$unionWith to combine documents from all four years:$unionWith组合所有四年的文档:
db.sales_2017.aggregate( [
{ $unionWith: "sales_2018" },
{ $unionWith: "sales_2019" },
{ $unionWith: "sales_2020" },
{ $group: { _id: "$item", total: { $sum: "$quantity" } } },
{ $sort: { total: -1 } }
] )
The sequence of$unionWithstages retrieve documents from the specified collections into the pipeline:$unionWith阶段的顺序将文档从指定集合检索到管道中:The$groupstage groups by theitemfield and uses$sumto calculate the total sales quantity peritem.$group阶段按item字段分组,并使用$sum计算每个item的总销售数量。The$sortstage orders the documents by descendingtotal.$sort阶段按total(总数)降序排列文档。
Pipeline output:管道输出:
{ "_id" : "Cookies", "total" : 1720 }
{ "_id" : "Chocolates", "total" : 1250 }
{ "_id" : "Nuts", "total" : 510 }
{ "_id" : "Pie", "total" : 395 }
{ "_id" : "Cheese", "total" : 350 }Create a Union with Specified Documents使用指定文档创建联盟
You can use 您可以使用$unionWith to perform a union with documents that you specify in the pipeline field. When you specify a $documents stage in the pipeline field, you perform a union with documents that aren't stored in a separate collection.$unionWith与您在pipeline字段中指定的文档执行联合。当您在管道字段中指定$documents阶段时,您将与未存储在单独集合中的文档执行联合。
Create a collection 创建一个集合cakeFlavors:cakeFlavors:
db.cakeFlavors.insertMany( [
{ _id: 1, flavor: "chocolate" },
{ _id: 2, flavor: "strawberry" },
{ _id: 3, flavor: "cherry" }
] )
The following 以下$unionWith operation performs a union with documents specified in the pipeline $documents field:$unionWith操作与pipeline $documents字段中指定的文档执行联合:
db.cakeFlavors.aggregate( [
{
$unionWith: {
pipeline: [
{
$documents: [
{ _id: 4, flavor: "orange" },
{ _id: 5, flavor: "vanilla", price: 20 }
]
}
]
}
}
] )
Output:输出:
[
{ _id: 1, flavor: 'chocolate' },
{ _id: 2, flavor: 'strawberry' },
{ _id: 3, flavor: 'cherry' },
{ _id: 4, flavor: 'orange' },
{ _id: 5, flavor: 'vanilla', price: 20 }
]Namespaces in Subpipelines子管道中的命名空间
Starting in MongoDB 8.0, namespaces in subpipelines within 从MongoDB 8.0开始,$lookup and $unionWith are validated to ensure the correct use of from and coll fields:$lookup和$unionWith子管道中的命名空间经过验证,以确保from和coll字段的正确使用:
For对于$lookup, omit thefromfield if you use a subpipeline with a stage which doesn't require a specified collection. For example, a$documentsstage.$lookup,如果您使用的子管道具有不需要指定集合的阶段,请省略from字段。例如,$documents阶段。Similarly, for同样,对于$unionWith, omit thecollfield.$unionWith,省略coll字段。
Unchanged behavior:行为不变:
For a对于以集合的阶段开始的$lookupthat starts with a stage for a collection, for example a$matchor$collStatssubpipeline, you must include thefromfield and specify the collection.$lookup,例如$match或$collStats子管道,您必须包含from字段并指定集合。Similarly, for同样,对于$unionWith, include thecollfield and specify the collection.$unionWith,包含coll字段并指定集合。
The following scenario shows an example.以下场景显示了一个示例。
Create a collection 创建一个集合cakeFlavors:cakeFlavors:
db.cakeFlavors.insertMany( [
{ _id: 1, flavor: "chocolate" },
{ _id: 2, flavor: "strawberry" },
{ _id: 3, flavor: "cherry" }
] )
Starting in MongoDB 8.0, the following example returns an error because it contains an invalid 从MongoDB 8.0开始,以下示例返回错误,因为它包含无效的coll field:coll字段:
db.cakeFlavors.aggregate( [ {
$unionWith: {
coll: "cakeFlavors",
pipeline: [ { $documents: [] } ] }
} ] )
In MongoDB versions before 8.0, the previous example runs.在MongoDB 8.0之前的版本中,前面的示例运行。
For an example with a valid 有关具有有效coll field, see Duplicate Results.coll字段的示例,请参阅重复结果。
C#
The C# examples on this page use the 本页上的C#示例使用Atlas示例数据集中的sample_mflix database from the Atlas sample datasets. sample_mflix数据库。To learn how to create a free MongoDB Atlas cluster and load the sample datasets, see Get Started in the MongoDB .NET/C# Driver documentation.要了解如何创建免费的MongoDB Atlas集群并加载示例数据集,请参阅MongoDB NET/C#驱动程序文档中的入门。
The following 以下Movie class models the documents in the sample_mflix.movies collection:Movie类对sample_mflix.movies集合中的文档进行建模:
public class Movie
{
public ObjectId Id { get; set; }
public int Runtime { get; set; }
public string Title { get; set; }
public string Rated { get; set; }
public List<string> Genres { get; set; }
public string Plot { get; set; }
public ImdbData Imdb { get; set; }
public int Year { get; set; }
public int Index { get; set; }
public string[] Comments { get; set; }
[]
public DateTime LastUpdated { get; set; }
}
Note
ConventionPack for Pascal CasePascal大小写的约定包
The C# classes on this page use Pascal case for their property names, but the field names in the MongoDB collection use camel case. To account for this difference, you can use the following code to register a 此页面上的C#类使用Pascal大小写作为其属性名,但MongoDB集合中的字段名使用驼峰大小写。为了解释这种差异,您可以在应用程序启动时使用以下代码注册ConventionPack when your application starts:ConventionPack:
var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() };
ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);To use the MongoDB .NET/C# driver to add a 要使用MongoDB .NET/C#驱动程序将$unionWith stage to an aggregation pipeline, call the UnionWith() method on a PipelineDefinition object.$unionWith阶段添加到聚合管道中,请在PipelineDefinition对象上调用UnionWith()方法。
The following example creates a pipeline stage that combines the incoming documents from the 以下示例创建了一个管道阶段,该阶段将来自sample_mflix.movies collection with the Movie documents in the sample_mflix.Movies collection:sample_mflix.movies集合的传入文档与sample_mflix.Movies集合中的Movie文档组合在一起:
var firstMovieCollection = client.GetDatabase("sample_mflix").GetCollection<Movie>("movies");
var secondMovieCollection = client.GetDatabase("sample_mflix").GetCollection<Movie>("Movies");
var pipeline = new EmptyPipelineDefinition<Movie>()
.UnionWith(
withCollection: secondMovieCollection,
withPipeline: new EmptyPipelineDefinition<Movie>());
var allMovieDocuments = firstMovieCollection.Aggregate(pipeline); Node.js
The Node.js examples on this page use the 本页上的Node.js示例使用Atlas示例数据集中的sample_mflix database from the Atlas sample datasets. sample_mflix数据库。To learn how to create a free MongoDB Atlas cluster and load the sample datasets, see Get Started in the MongoDB Node.js driver documentation.要了解如何创建免费的MongoDB Atlas集群并加载示例数据集,请参阅MongoDB Node.js驱动程序文档中的入门。
To use the MongoDB Node.js driver to add a 要使用MongoDB Node.js驱动程序将$unionWith stage to an aggregation pipeline, use the $unionWith operator in a pipeline object.$unionWith阶段添加到聚合管道中,请在管道对象中使用$unionWith运算符。
The following example creates a pipeline stage that combines the incoming documents from the 以下示例创建了一个管道阶段,该阶段将来自sample_mflix.movies collection with the movie documents in the sample_mflix.Movies collection. The example then runs the aggregation pipeline: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;