$addFields (聚合)
定义
$addFields
向文档中添加新字段。
$addFields
输出包含输入文档中所有现有字段和新添加字段的文档。关于
$addFields
阶段相当于一个$project
阶段,该阶段明确指定输入文档中的所有现有字段并添加新字段。注意
您还可以使用
$set
阶段,它是$addFields
的别称。
兼容性
您可以在以下环境中使用 $addFields
MongoDB Atlas:云中 MongoDB 部署的全托管服务
MongoDB Enterprise:基于订阅的自托管 MongoDB 版本
MongoDB Community:源代码可用的、免费使用且自托管的 MongoDB 版本
语法
阶段具有以下语法
{ $addFields: { <newField>: <expression>, ... } }
指定要添加的字段名称并将其值设置为聚合表达式或空对象。有关表达式更多信息,请参阅表达式运算符。
重要
如果新字段的名称与现有字段名称(包括_id
)相同,则$addFields
会使用指定的表达式值覆盖该字段的现有值。
行为
$addFields
会将新字段追加到现有文档中。您可以在聚合操作中包含一个或多个$addFields
阶段。$addFields
接受将对象嵌入其中,您可以将其值设置为聚合表达式或空对象。例如,以下嵌套对象是可接受的{$addFields: { a: { b: { } } } } 要向嵌入文档(包括数组中的文档)添加字段,请使用点符号。请参阅示例。
要使用
$addFields
向现有数组字段添加元素,请与$concatArrays
一起使用。请参阅示例。
示例
使用两个 $addFields
阶段
名为 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 } ] )
以下操作使用两个 $addFields
阶段将三个新字段包含在输出文档中
db.scores.aggregate( [ { $addFields: { totalHomework: { $sum: "$homework" } , totalQuiz: { $sum: "$quiz" } } }, { $addFields: { totalScore: { $add: [ "$totalHomework", "$totalQuiz", "$extraCredit" ] } } } ] )
操作返回以下文档
[ { _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 } ]
向嵌套文档添加字段
使用点表示法向嵌套文档添加新字段。
例如,创建一个包含以下文档的名为 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" } ] )
以下聚合操作向嵌套文档 specs
添加一个新字段 fuel_type
。
db.vehicles.aggregate( [ { $addFields: { "specs.fuel_type": "unleaded" } } ] )
操作返回以下结果
[ { _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" } } ]
覆盖现有字段
在$addFields
操作中指定现有字段名称会导致原始字段被替换。
名为animals
的集合包含以下文档
db.animals.insertOne( { _id: 1, dogs: 10, cats: 15 } )
以下$addFields
操作指定了cats
字段。
db.animals.aggregate( [ { $addFields: { cats: 20 } } ] )
操作返回以下文档
[ { _id: 1, dogs: 10, cats: 20 } ]
可以替换一个字段为另一个字段。在以下示例中,item
字段替换了_id
字段。
名为fruit
的集合包含以下文档
db.fruit.insertMany( [ { _id: 1, item: "tangerine", type: "citrus" }, { _id: 2, item: "lemon", type: "citrus" }, { _id: 3, item: "grapefruit", type: "citrus" } ] )
以下聚合操作使用$addFields
将每个文档的_id
字段替换为item
字段的值,并将item
字段替换为一个静态值。
db.fruit.aggregate( [ { $addFields: { _id : "$item", item: "fruit" } } ] )
操作返回以下内容
[ { _id: "tangerine", item: "fruit", type: "citrus" }, { _id: "lemon", item: "fruit", type: "citrus" }, { _id: "grapefruit", item: "fruit", type: "citrus" } ]
向数组中添加元素
创建一个名为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 } ] )
可以使用$addFields
与一个$concatArrays
表达式一起使用,向现有数组字段添加元素。例如,以下操作使用$addFields
将homework
字段替换为一个新的数组,其元素是当前的homework
数组与包含新分数[ 7 ]
的数组的连接。
db.scores.aggregate( [ { $match: { _id: 1 } }, { $addFields: { homework: { $concatArrays: [ "$homework", [ 7 ] ] } } } ] )
操作返回以下内容
[ { _id: 1, student: "Maya", homework: [ 10, 5, 10, 7 ], quiz: [ 10, 8 ], extraCredit: 0 } ]
删除字段
您可以使用$addFields
与
变量来删除文档字段。$$REMOVE
例如,创建一个labReadings
集合
db.labReadings.insertMany( [ { date: ISODate("2024-10-09"), temperature: 80 }, { date: null, temperature: 83 }, { date: ISODate("2024-12-09"), temperature: 85 } ] )
要从labReadings
文档中删除date
字段,请使用带有$$REMOVE
变量的$addFields
db.labReadings.aggregate( [ { $addFields: { date: "$$REMOVE" } } ] )
输出
[ { _id: ObjectId('671285306fd2c3b24f2e7eaa'), temperature: 80 }, { _id: ObjectId('671285306fd2c3b24f2e7eab'), temperature: 83 }, { _id: ObjectId('671285306fd2c3b24f2e7eac'), temperature: 85 } ]
您还可以使用$$REMOVE
来有条件地删除字段。例如,以下聚合操作在date
为null
的文档中删除date
字段
db.labReadings.aggregate( [ { $addFields: { date: { $ifNull: [ "$date", "$$REMOVE" ] } } } ] )
输出
[ { _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 } ]
提示
与$project比较
您可以使用$addFields
或$project
阶段来删除文档字段。最佳方法取决于您的管道以及您希望保留原始文档的多少。
有关在$project
阶段使用$$REMOVE
的示例,请参阅有条件排除字段。