$unionWith (aggregation)
本页面
定义
语法
$unionWith
阶段具有以下语法
{ $unionWith: { coll: "<collection>", pipeline: [ <stage1>, ... ] } }
要包含指定集合中的所有文档而不进行任何处理,您可以使用简化的形式
{ $unionWith: "<collection>" } // Include all documents from the specified collection
$unionWith
阶段接受以下字段的文档
字段 | 必要性 | 描述 |
---|---|---|
如果省略 pipeline 则是必需的。否则是可选的。 | 包含您希望包含在结果集中的结果集的集合或视图的 管道。 如果您省略了 | |
如果省略了 coll ,则为必选。否则为可选。 | 应用于输入文档的聚合管道。
管道不能包含 |
$unionWith
操作将对应以下SQL语句
SELECT * FROM Collection1 WHERE ... UNION ALL SELECT * FROM Collection2 WHERE ...
考虑事项
重复结果
上一阶段和$unionWith
阶段的组合结果可能包含重复项。
例如,创建一个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" }, ])
以下聚合结合了从 suppliers
和 warehouse
集合中投影出的 state
字段结果。
db.suppliers.aggregate([ { $project: { state: 1, _id: 0 } }, { $unionWith: { coll: "warehouses", pipeline: [ { $project: { state: 1, _id: 0 } } ]} } ])
结果集包含重复项
{ "state" : "Texas" } { "state" : "Colorado" } { "state" : "Rhode Island" } { "state" : "California" } { "state" : "Colorado" } { "state" : "Florida" }
要删除重复项,您可以在按 state
字段分组的基础上包含一个 $group
阶段
db.suppliers.aggregate([ { $project: { state: 1, _id: 0 } }, { $unionWith: { coll: "warehouses", pipeline: [ { $project: { state: 1, _id: 0 } } ]} }, { $group: { _id: "$state" } } ])
结果集不再包含重复项
{ "_id" : "California" } { "_id" : "Texas" } { "_id" : "Florida" } { "_id" : "Colorado" } { "_id" : "Rhode Island" }
与分片集合 $unionWith
结合
如果 $unionWith
阶段是 $lookup pipeline 的一部分,则 $unionWith
coll 不能是分片的。例如,在以下聚合操作中,inventory_q1
集合不能是分片的
db.suppliers.aggregate([ { $lookup: { from: "warehouses", let: { order_item: "$item", order_qty: "$ordered" }, pipeline: [ ... { $unionWith: { coll: "inventory_q1", pipeline: [ ... ] } }, ... ], as: "stockdata" } } ])
校对
如果 db.collection.aggregate()
包含一个 collation
文档,则该校对用于操作,忽略任何其他校对。
如果 db.collection.aggregate()
不包含 collation
文档,则 db.collection.aggregate()
方法使用 db.collection.aggregate()
在其上运行的顶层集合/视图的校对。
如果 $unionWith coll 是一个集合,则忽略其校对。
如果 $unionWith coll 是一个 视图,则其校对必须与顶层集合/视图匹配。否则,操作会出错。
Atlas Search 支持链接
从 MongoDB 6.0 开始,您可以在 Atlas Search $search
或 $searchMeta
阶段中指定 $unionWith
管道,以在 Atlas 集群上搜索集合。在 $unionWith
管道内部,$search
或 $searchMeta
阶段必须是第一个阶段。
[{ "$unionWith": { "coll": <collection-name>, "pipeline": [{ "$search": { "<operator>": { <operator-specification> } }, ... }] } }]
[{ "$unionWith": { "coll": <collection-name>, "pipeline": [{ "$searchMeta": { "<collector>": { <collector-specification> } }, ... }] } }]
要查看 $unionWith
与 $search
的示例,请参阅 Atlas Search 教程 使用 $unionWith 运行 Atlas Search $search 查询。
限制
限制 | 描述 |
---|---|
聚合管道不能在事务中使用 $unionWith 。 | |
分片集合 | |
$unionWith pipeline不能包含 $out 阶段。 | |
$unionWith pipeline不能包含 $merge 阶段。 |
示例
从年度数据集合的并集中创建销售报告
以下示例使用$unionWith
阶段将数据合并并从多个集合中返回结果。在这些示例中,每个集合包含一年的销售数据。
填充示例数据
创建包含以下文档的
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 } ] ) 创建包含以下文档的
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 } ] ) 创建一个包含以下文档的
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 } ] ) 创建一个包含以下文档的
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 } ] )
报告1:按年份、店铺和项目划分的所有销售
以下聚合创建了一个按季度和店铺列出的年度销售报告。该管道使用$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 } } ] )
具体来说,聚合管道使用
$set
阶段更新_id
字段,使其包含年份。一系列
$unionWith
阶段将所有四个集合中的文档合并在一起,每个阶段也对其文档使用$set
阶段。$sort
阶段按_id
(年份)、store
和item
排序。
管道输出
{ "_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 }
报告2:按项目分组的销售汇总
以下聚合创建了一个列出每个项目销售量的销售报告。该管道使用$unionWith
将来自所有四个年份的文档合并
db.sales_2017.aggregate( [ { $unionWith: "sales_2018" }, { $unionWith: "sales_2019" }, { $unionWith: "sales_2020" }, { $group: { _id: "$item", total: { $sum: "$quantity" } } }, { $sort: { total: -1 } } ] )
$unionWith
阶段序列从指定的集合检索文档到管道《$sort》阶段按降序对文档中的
total
进行排序。
管道输出
{ "_id" : "Cookies", "total" : 1720 } { "_id" : "Chocolates", "total" : 1250 } { "_id" : "Nuts", "total" : 510 } { "_id" : "Pie", "total" : 395 } { "_id" : "Cheese", "total" : 350 }
创建指定文档的联合
您可以使用 $unionWith
来对在 pipeline
字段中指定的文档进行联合操作。当您在 pipeline
字段中指定一个 $documents
阶段时,您将执行与未存储在单独集合中的文档的联合。
创建一个 cakeFlavors
集合
db.cakeFlavors.insertMany( [ { _id: 1, flavor: "chocolate" }, { _id: 2, flavor: "strawberry" }, { _id: 3, flavor: "cherry" } ] )
以下 $unionWith
操作执行了在 pipeline
字段中指定的文档的联合操作
db.cakeFlavors.aggregate( [ { $unionWith: { pipeline: [ { $documents: [ { _id: 4, flavor: "orange" }, { _id: 5, flavor: "vanilla", price: 20 } ] } ] } } ] )
输出
[ { _id: 1, flavor: 'chocolate' }, { _id: 2, flavor: 'strawberry' }, { _id: 3, flavor: 'cherry' }, { _id: 4, flavor: 'orange' }, { _id: 5, flavor: 'vanilla', price: 20 } ]
子管道中的命名空间
从 MongoDB 8.0 开始,对 $lookup
和 $unionWith
中的子管道命名空间进行验证,以确保正确使用 from
和 coll
字段。
对于
$lookup
,如果您使用了一个不需要指定集合的子管道阶段,则省略from
字段。例如,一个$documents
阶段。类似地,对于
$unionWith
,省略coll
字段。
不变的行为
对于以集合阶段开始的
$lookup
,例如$match
或$collStats
子管道,您必须包含from
字段并指定集合。同样,对于
$unionWith
,包括coll
字段并指定集合。
以下场景展示了一个例子。
创建一个 cakeFlavors
集合
db.cakeFlavors.insertMany( [ { _id: 1, flavor: "chocolate" }, { _id: 2, flavor: "strawberry" }, { _id: 3, flavor: "cherry" } ] )
从MongoDB 8.0版本开始,以下示例返回一个错误,因为它包含一个无效的coll
字段
db.cakeFlavors.aggregate( [ { $unionWith: { coll: "cakeFlavors", pipeline: [ { $documents: [] } ] } } ] )
在MongoDB 8.0之前的版本中,之前的示例可以运行。
有关具有有效coll
字段的示例,请参阅重复结果。