Database Manual / Reference / Query Language / Aggregation Stages

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

Definition定义

$addFields

Adds new fields to documents. $addFields outputs documents that contain all existing fields from the input documents and newly added fields.向文档中添加新字段。$addFields输出包含输入文档中所有现有字段和新添加字段的文档。

The $addFields stage is equivalent to a $project stage that explicitly specifies all existing fields in the input documents and adds the new fields.$addFields阶段相当于$project阶段,它明确指定输入文档中的所有现有字段并添加新字段。

Note

You can also use the $set stage, which is an alias for $addFields.您还可以使用$set stage,它是$addFields的别名。

Compatibility兼容性

You can use $addFields for deployments hosted in the following environments:您可以将$addFields用于在以下环境中托管的部署:

  • MongoDB Atlas: The fully managed service for MongoDB deployments in the cloud:云中MongoDB部署的完全托管服务
  • MongoDB Enterprise: The subscription-based, self-managed version of MongoDB:MongoDB的基于订阅的自我管理版本
  • MongoDB Community: The source-available, free-to-use, and self-managed version of MongoDB:MongoDB的源代码可用、免费使用和自我管理版本

Syntax语法

The stage has the following syntax:该阶段具有以下语法:

{ $addFields: { <newField>: <expression>, ... } }

Specify the name of each field to add and set its value to an aggregation expression or an empty object. For more information on expressions, see Expressions.指定要添加的每个字段的名称,并将其值设置为聚合表达式或空对象。有关表达式的详细信息,请参阅表达式

Important

If the name of the new field is the same as an existing field name (including _id), $addFields overwrites the existing value of that field with the value of the specified expression.如果新字段的名称与现有字段名称(包括_id)相同,$addFields将用指定表达式的值覆盖该字段的现有值。

Behavior行为

  • $addFields appends new fields to existing documents. You can include one or more $addFields stages in an aggregation operation.将新字段附加到现有文档中。您可以在聚合操作中包含一个或多个$addFields阶段。
  • $addFields accepts the embedding of objects where you can set a value to an aggregation expression or to an empty object. For example, the following nested objects are accepted:接受对象的嵌入,您可以在其中为聚合表达式或空对象设置值。例如,接受以下嵌套对象:

    {$addFields: { a: { b: { } } } }

    To add a field or fields to embedded documents (including documents in arrays) use the dot notation. See example.要向嵌入式文档(包括数组中的文档)添加一个或多个字段,请使用点符号。参见示例

  • To add an element to an existing array field with $addFields, use with $concatArrays. 要使用$addFields向现有数组字段添加元素,请与$concatArrays一起使用。See example.请参阅示例

Examples示例

MongoDB Shell

Using Two $addFields Stages使用两个$addFields阶段

A collection called scores contains the following documents:名为scores的集合包含以下文档:

db.scores.insertMany( [
{
_id: 1,
student: "Maya",
homework: [ 10, 5, 10 ],
quiz: [ 10, 8 ],
extraCredit: 0
},
{
_id: 2,
student: "Ryan",
homework: [ 5, 6, 5 ],
quiz: [ 8, 8 ],
extraCredit: 8
}
] )

The following operation uses two $addFields stages to include three new fields in the output documents:以下操作使用两个$addFields阶段在输出文档中包含三个新字段:

db.scores.aggregate( [
{
$addFields: {
totalHomework: { $sum: "$homework" } ,
totalQuiz: { $sum: "$quiz" }
}
},
{
$addFields: { totalScore:
{ $add: [ "$totalHomework", "$totalQuiz", "$extraCredit" ] } }
}
] )

The operation returns the following documents:该操作返回以下文档:

[
{
_id: 1,
student: "Maya",
homework: [ 10, 5, 10 ],
quiz: [ 10, 8 ],
extraCredit: 0,
totalHomework: 25,
totalQuiz: 18,
totalScore: 43
},
{
_id: 2,
student: "Ryan",
homework: [ 5, 6, 5 ],
quiz: [ 8, 8 ],
extraCredit: 8,
totalHomework: 16,
totalQuiz: 16,
totalScore: 40
}
]

Adding Fields to an Embedded Document向嵌入式文档添加字段

Use dot notation to add new fields to embedded documents.使用点符号向嵌入式文档添加新字段。

For example, create a collection called vehicles with the following documents:例如,使用以下文档创建一个名为vehicles的集合:

db.vehicles.insertMany( [
{ _id: 1, type: "car", specs: { doors: 4, wheels: 4 } },
{ _id: 2, type: "motorcycle", specs: { doors: 0, wheels: 2 } },
{ _id: 3, type: "jet ski" }
] )

The following aggregation operation adds a new field fuel_type to the embedded document specs.以下聚合操作将一个新的字段fuel_type添加到嵌入式文档specs中。

db.vehicles.aggregate( [
{ $addFields: { "specs.fuel_type": "unleaded" } }
] )

The operation returns the following results:该操作返回以下结果:

[
{ _id: 1, type: "car",
specs: { doors: 4, wheels: 4, fuel_type: "unleaded" } },
{ _id: 2, type: "motorcycle",
specs: { doors: 0, wheels: 2, fuel_type: "unleaded" } },
{ _id: 3, type: "jet ski",
specs: { fuel_type: "unleaded" } }
]

Overwriting an existing field覆盖现有字段

Specifying an existing field name in an $addFields operation causes the original field to be replaced.$addFields操作中指定现有字段名会导致替换原始字段。

A collection called animals contains the following document:一个名为animals的集合包含以下文件:

db.animals.insertOne(
{ _id: 1, dogs: 10, cats: 15 }
)

The following $addFields operation specifies the cats field.以下$addFields操作指定了cats字段。

db.animals.aggregate( [
{
$addFields: { cats: 20 }
}
] )

The operation returns the following document:该操作返回以下文档:

[ { _id: 1, dogs: 10, cats: 20 } ]

It is possible to replace one field with another. In the following example the item field substitutes for the _id field.可以用另一个字段替换一个字段。在以下示例中,item字段替换_id字段。

A collection called fruit contains the following documents:一个名为fruit的集合包含以下文档:

db.fruit.insertMany( [
{ _id: 1, item: "tangerine", type: "citrus" },
{ _id: 2, item: "lemon", type: "citrus" },
{ _id: 3, item: "grapefruit", type: "citrus" }
] )

The following aggregation operation uses $addFields to replace the _id field of each document with the value of the item field, and replaces the item field with a static value.以下聚合操作使用$addFields将每个文档的_id字段替换为item字段的值,并将item字段替换为静态值。

db.fruit.aggregate( [
{
$addFields: {
_id : "$item",
item: "fruit"
}
}
] )

The operation returns the following:该操作返回以下内容:

[
{ _id: "tangerine", item: "fruit", type: "citrus" },
{ _id: "lemon", item: "fruit", type: "citrus" },
{ _id: "grapefruit", item: "fruit", type: "citrus" }
]

Add Element to an Array向数组添加元素

Create a sample scores collection with the following:使用以下内容创建样本scores集合:

db.scores.insertMany( [
{ _id: 1, student: "Maya", homework: [ 10, 5, 10 ], quiz: [ 10, 8 ], extraCredit: 0 },
{ _id: 2, student: "Ryan", homework: [ 5, 6, 5 ], quiz: [ 8, 8 ], extraCredit: 8 }
] )

You can use $addFields with a $concatArrays expression to add an element to an existing array field. 您可以将$addFields$concatArrays表达式一起使用,向现有数组字段添加元素。For example, the following operation uses $addFields to replace the homework field with a new array whose elements are the current homework array concatenated with another array containing a new score [ 7 ].例如,以下操作使用$addFieldshomework字段替换为一个新数组,该数组的元素是当前homework数组与包含新分数的另一个数组连接起来的元素[7]

db.scores.aggregate( [
{ $match: { _id: 1 } },
{ $addFields: { homework: { $concatArrays: [ "$homework", [ 7 ] ] } } }
] )

The operation returns the following:该操作返回以下内容:

[ { _id: 1, student: "Maya", homework: [ 10, 5, 10, 7 ], quiz: [ 10, 8 ], extraCredit: 0 } ]

Remove Fields删除字段

You can use $addFields with the $$REMOVE variable to remove document fields.您可以使用$addFields$$REMOVE变量来删除文档字段。

For example, create a labReadings collection:例如,创建一个labReadings集合:

db.labReadings.insertMany( [
{
date: ISODate("2024-10-09"),
temperature: 80
},
{
date: null,
temperature: 83
},
{
date: ISODate("2024-12-09"),
temperature: 85
}
] )

To remove the date field from the labReadings documents, use $addFields with the $$REMOVE variable:要从labReadings文档中删除日期字段,请使用$addFields$$remove变量:

db.labReadings.aggregate( [
{
$addFields: { date: "$$REMOVE" }
}
] )

Output:输出

[
{ _id: ObjectId('671285306fd2c3b24f2e7eaa'), temperature: 80 },
{ _id: ObjectId('671285306fd2c3b24f2e7eab'), temperature: 83 },
{ _id: ObjectId('671285306fd2c3b24f2e7eac'), temperature: 85 }
]

You can also use $$REMOVE to conditionally remove fields. For example, the following aggregation removes the date field from documents where date is null:您还可以使用$$REMOVE有条件地删除字段。例如,以下聚合从datenull的文档中删除date字段:

db.labReadings.aggregate( [
{
$addFields:
{
date: {
$ifNull: [ "$date", "$$REMOVE" ]
}
}
}
] )

Output:输出

[
{
_id: ObjectId('671285306fd2c3b24f2e7eaa'),
date: ISODate('2024-10-09T00:00:00.000Z'),
temperature: 80
}, { _id: ObjectId('671285306fd2c3b24f2e7eab'), temperature: 83 },
{
_id: ObjectId('671285306fd2c3b24f2e7eac'),
date: ISODate('2024-12-09T00:00:00.000Z'),
temperature: 85
}
]
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 $addFields stage to an aggregation pipeline, use the $addFields operator in a pipeline object.要使用MongoDB Node.js驱动程序将$addFields阶段添加到聚合管道中,请在管道对象中使用$addFields运算符。

The following example creates a pipeline stage that adds a totalReviews field to each movie document, which contains the movie's total number of reviews. The example then runs the aggregation pipeline:以下示例创建了一个管道阶段,该阶段将totalReviews字段添加到每个电影文档中,其中包含电影的评论总数。然后,该示例运行聚合管道:

const pipeline = [
{
$addFields: {
totalReviews: {
$add: ["$imdb.votes", "$tomatoes.viewer.numReviews"]
}
}
}
];

const cursor = collection.aggregate(pipeline);
return cursor;

Tip

Comparison with $project$project比较

You can use either the $addFields or $project stage to remove document fields. The best approach depends on your pipeline and how much of the original document you want to retain.您可以使用$addFields$project阶段删除文档字段。最佳方法取决于您的管道以及您希望保留多少原始文档。

For an example using $$REMOVE in a $project stage, see Conditionally Exclude Fields.有关在$project阶段使用$$REMOVE的示例,请参阅有条件排除字段

Learn More了解更多

To learn more about related pipeline stages, see the $project and $set guides.要了解有关相关管道阶段的更多信息,请参阅$project$set指南。