本文主要介绍MongoDB聚合的$addField阶段的使用方法。
为文档添加新字段,$addFields
阶段输出文档包含了输入文档的全部字段和新增的字段。
$addFields
阶段等价于$project
阶段明确指定了输入文档的所有字段和新增字段。
注意:
MongoDB从4.2版本开始,增加了增加了一个新的阶段$set
,是$addFields
阶段的别名
$addFields
阶段的语法:
{ $addFields: { <newField>: <expression>, ... } }
指定所有新增字段的名称和值,值可以是表达式或空对象。
重点:
如果新字段的名称与已有字段的名称重复(包括_id
),$addFields
将使用指定表达式的值覆盖已有字段的值。
$addFields
阶段可以为文档增加一个或多个新字段。
$addFields
阶段存在于聚合操作。
$addFields
的值可以接受嵌套对象,也可以是聚合表达式或一个空对象,下面的内嵌对象是可接受的:
{$addFields: { a: { b: { } } } }
添加一个或多个字段到内嵌文档(数组文档)使用点符号。
$addFields
与$concatArrays
可以为已有数组字段添加元素。
$addFields
阶段集合scores
包含以下文档:
{
_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
集合中包含如下文档:
{ _id: 1, dogs: 10, cats: 15 }
下面的$addFields
操作指定了cats
字段:
db.animals.aggregate( [
{
$addFields: { "cats": 20 }
}
] )
操作后返回的文档如下:
{ _id: 1, dogs: 10, cats: 20 }
可以用一个字段替换另一个字段。在下面的示例中,用item
字段替代了_id
字段。
fruit
集合中包含了以下文档:
{ "_id" : 1, "item" : "tangerine", "type" : "citrus" }
{ "_id" : 2, "item" : "lemon", "type" : "citrus" }
{ "_id" : 3, "item" : "grapefruit", "type" : "citrus" }
下面的$addFields
聚合操作使用item
字段替换了所有的_id
字段的值,并用常量替换了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 }