Database Manual / Reference / Query Language / Aggregation Stages

$unionWith (aggregation stage)(聚合阶段)

Definition定义

$unionWith

Changed in version 8.0.在版本8.0中更改。

Combines two aggregations into a single result set. $unionWith outputs 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阶段接收具有以下字段的文档:

Field字段Necessity必要性Description描述
collRequired if pipeline is omitted. Otherwise optional.如果省略了pipeline,则需要。否则可选。

The collection or view whose pipeline results you wish to include in the result set.您希望将其管道结果包含在结果集中的集合或视图。

If you omit the coll field, you must specify a pipeline field with a first stage of $documents.如果省略coll字段,则必须指定pipeline字段,它使用$documents作为第一阶段。

pipelineRequired if coll is omitted. Otherwise optional.如果省略了coll,则为必填项。否则可选。

An aggregation pipeline to apply to the input documents.应用于输入文档的聚合管道。

  • If you specify coll, the pipeline applies to the documents in coll.如果指定coll,则管道将应用于coll中的文档。
  • If you omit coll, the pipeline applies to the documents in the pipeline's $documents stage. For an example, see Create a Union with Specified Documents.如果省略coll,则管道将应用于管道的$documents阶段中的文档。例如,请参阅使用指定文档创建联合

The pipeline cannot include the $out and $merge stages.管道不能包括$out$merge阶段。 Starting in v6.0, the pipeline can contain the MongoDB Search $search stage as the first stage inside the pipeline. 从v6.0开始,pipeline可以包含MongoDB Search$Search阶段作为pipeline内的第一阶段。To learn more, see MongoDB Search Support.要了解更多信息,请参阅MongoDB搜索支持

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.以下聚合组合了来自supplierswarehouse集合的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.如果$unionWith coll一个集合,则忽略其排序规则。
  • If the $unionWith coll is a view, then its collation must match that of the top-level collection/view. 如果$unionWith coll是视图,则其排序规则必须与顶级集合/视图的排序规则匹配。Otherwise, the operation errors.否则,操作错误。

MongoDB Search SupportMongoDB搜索支持

Starting in MongoDB 6.0, you can specify the MongoDB Search $search or $searchMeta stage in the $unionWith pipeline to search collections on the Atlas cluster. 从MongoDB 6.0开始,您可以在$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限制

Restrictions限制Description描述
transactionsAn aggregation pipeline cannot use $unionWith inside transactions.聚合管道不能在内部事务中使用$unionWith
Sharded Collection分片集合If the $unionWith stage is part of the pipeline, the $unionWith coll cannot be sharded.如果$unionWith阶段是管道的一部分,则$unionWith coll不能被分片。
$outThe $unionWith pipeline cannot include the $out stage.$unionWith pipeline不能包含$out阶段。
$mergeThe $unionWith pipeline cannot include the $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填充样本数据

  1. Create a sales_2017 collection 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 }
    ] )
  2. Create a sales_2018 collection 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 }
    ] )
  3. Create a sales_2019 collection 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 }
    ] )
  4. Create a sales_2020 collection 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 $set stage to update the _id field to contain the year.一个$set阶段,用于更新_id字段以包含年份。
  • A sequence of $unionWith stages to combine all documents from the four collections, each also using the $set stage on its documents.一系列$unionWith阶段,用于组合四个集合中的所有文档,每个集合也在其文档上使用$set阶段。
  • A $sort stage to sort by the _id (the year), the store, and item.$sort阶段,按_id(年份)、storeitem进行排序。

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 $unionWith stages retrieve documents from the specified collections into the pipeline:$unionWith阶段的顺序将文档从指定集合检索到管道中:
  • The $group stage groups by the item field and uses $sum to calculate the total sales quantity per item.$group阶段按item字段分组,并使用$sum计算每个item的总销售数量。
  • The $sort stage orders the documents by descending total.$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 $lookup and $unionWith are validated to ensure the correct use of from and coll fields:从MongoDB 8.0开始,$lookup$unionWith子管道中的命名空间经过验证,以确保fromcoll字段的正确使用:

  • For $lookup, omit the from field if you use a subpipeline with a stage which doesn't require a specified collection. For example, a $documents stage.对于$lookup,如果您使用的子管道具有不需要指定集合的阶段,请省略from字段。例如,$documents阶段。
  • Similarly, for $unionWith, omit the coll field.同样,对于$unionWith,省略coll字段。

Unchanged behavior:行为不变:

  • For a $lookup that starts with a stage for a collection, for example a $match or $collStats subpipeline, you must include the from field and specify the collection.对于以集合的阶段开始的$lookup,例如$match$collStats子管道,您必须包含from字段并指定集合。
  • Similarly, for $unionWith, include the coll field 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 coll field:从MongoDB 8.0开始,以下示例返回错误,因为它包含无效的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 sample_mflix database from the Atlas sample datasets. 本页上的C#示例使用Atlas示例数据集中的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; }

[BsonElement("lastupdated")]
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 ConventionPack when your application starts:此页面上的C#类使用Pascal大小写作为其属性名,但MongoDB集合中的字段名使用驼峰大小写。为了解释这种差异,您可以在应用程序启动时使用以下代码注册ConventionPack

var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() };
ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);

To use the MongoDB .NET/C# driver to add a $unionWith stage to an aggregation pipeline, call the UnionWith() method on a PipelineDefinition object.要使用MongoDB .NET/C#驱动程序将$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 sample_mflix database from the Atlas sample datasets. 本页上的Node.js示例使用Atlas示例数据集中的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 $unionWith stage to an aggregation pipeline, use the $unionWith operator in a pipeline object.要使用MongoDB Node.js驱动程序将$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;