使用聚合管道的更新
本页内容
要执行更新操作,您可以使用聚合管道。您可以在 MongoDB Atlas、MongoDB Compass、MongoDB Shell 或 Drivers 中构建和执行聚合管道以执行更新。MongoDB Atlas、MongoDB Compass、MongoDB Shell 或 驱动程序。
更新操作中,聚合管道可以包含以下阶段:
使用聚合管道可以创建更丰富的更新语句,例如根据当前字段值表达条件更新,或者使用另一个字段(或多个字段)的值来更新一个字段。
在Atlas中创建更新聚合管道
您可以使用MongoDB Atlas UI构建聚合管道以执行更新。要在MongoDB Atlas UI中创建和执行聚合管道,您必须拥有项目数据访问只读
角色或更高角色。
示例
以下示例演示了如何使用聚合管道阶段 $set
、$replaceRoot
和 $addFields
来执行更新。
使用 $set 的 updateOne
创建一个示例 students
集合(如果集合尚不存在,插入操作将创建集合)
db.students.insertMany( [ { _id: 1, test1: 95, test2: 92, test3: 90, modified: new Date("01/05/2020") }, { _id: 2, test1: 98, test2: 100, test3: 102, modified: new Date("01/05/2020") }, { _id: 3, test1: 95, test2: 110, modified: new Date("01/04/2020") } ] )
为了验证,查询集合
db.students.find()
以下 db.collection.updateOne()
操作使用聚合管道更新具有 _id: 3
的文档
db.students.updateOne( { _id: 3 }, [ { $set: { "test3": 98, modified: "$$NOW"} } ] )
具体来说,管道包括一个 $set
阶段,该阶段向文档添加 test3
字段(并将其值设置为 98
),并将 modified
字段设置为当前日期和时间。该操作使用聚合变量 NOW
来表示当前日期和时间。要访问变量,请使用 $$
前缀并使用引号括起来。
为了验证更新,您可以查询集合
db.students.find().pretty()
使用 $replaceRoot 和 $set 更新多个
创建一个示例 students2
集合(如果集合目前不存在,插入操作将创建集合)
db.students2.insertMany( [ { "_id" : 1, quiz1: 8, test2: 100, quiz2: 9, modified: new Date("01/05/2020") }, { "_id" : 2, quiz2: 5, test1: 80, test2: 89, modified: new Date("01/05/2020") }, ] )
为了验证,查询集合
db.students2.find()
以下 db.collection.updateMany()
操作使用聚合管道标准化文档的字段(即集合中的文档应具有相同的字段)并更新 modified
字段
db.students2.updateMany( {}, [ { $replaceRoot: { newRoot: { $mergeObjects: [ { quiz1: 0, quiz2: 0, test1: 0, test2: 0 }, "$$ROOT" ] } } }, { $set: { modified: "$$NOW"} } ] )
具体来说,管道包括
一个
$replaceRoot
阶段,使用$mergeObjects
表达式为quiz1
、quiz2
、test1
和test2
字段设置默认值。聚合变量ROOT
指的是当前正在修改的文档。要访问变量,请使用$$
前缀并加引号。当前文档字段将覆盖默认值。一个
$set
阶段,将modified
字段更新为当前日期和时间。该操作使用聚合变量NOW
来获取当前日期和时间。要访问变量,请使用$$
前缀并加引号。
为了验证更新,您可以查询集合
db.students2.find()
使用 $set 更新多个
创建一个示例 students3
集合(如果集合目前不存在,插入操作将创建集合)
db.students3.insertMany( [ { "_id" : 1, "tests" : [ 95, 92, 90 ], "modified" : ISODate("2019-01-01T00:00:00Z") }, { "_id" : 2, "tests" : [ 94, 88, 90 ], "modified" : ISODate("2019-01-01T00:00:00Z") }, { "_id" : 3, "tests" : [ 70, 75, 82 ], "modified" : ISODate("2019-01-01T00:00:00Z") } ] );
为了验证,查询集合
db.students3.find()
以下 db.collection.updateMany()
操作使用聚合管道更新文档,包括计算出的平均成绩和字母成绩。
db.students3.updateMany( { }, [ { $set: { average : { $trunc: [ { $avg: "$tests" }, 0 ] }, modified: "$$NOW" } }, { $set: { grade: { $switch: { branches: [ { case: { $gte: [ "$average", 90 ] }, then: "A" }, { case: { $gte: [ "$average", 80 ] }, then: "B" }, { case: { $gte: [ "$average", 70 ] }, then: "C" }, { case: { $gte: [ "$average", 60 ] }, then: "D" } ], default: "F" } } } } ] )
具体来说,管道包括
一个
$set
阶段,用于计算tests
数组元素的截断平均值,并将modified
字段更新为当前日期和时间。为了计算截断平均值,该阶段使用$avg
和$trunc
表达式。操作使用聚合变量NOW
来表示当前日期和时间。要访问变量,请使用$$
作为前缀,并用引号括起来。
为了验证更新,您可以查询集合
db.students3.find()
使用
创建一个示例 students4
集合(如果集合当前不存在,插入操作将创建集合)
db.students4.insertMany( [ { "_id" : 1, "quizzes" : [ 4, 6, 7 ] }, { "_id" : 2, "quizzes" : [ 5 ] }, { "_id" : 3, "quizzes" : [ 10, 10, 10 ] } ] )
为了验证,查询集合
db.students4.find()
以下 db.collection.updateOne()
操作使用聚合管道向具有 _id: 2
的文档添加测验分数
db.students4.updateOne( { _id: 2 }, [ { $set: { quizzes: { $concatArrays: [ "$quizzes", [ 8, 6 ] ] } } } ] )
为了验证更新,查询集合
db.students4.find()
使用
创建一个示例 temperatures
集合,其中包含摄氏度的温度(如果集合当前不存在,插入操作将创建集合)
db.temperatures.insertMany( [ { "_id" : 1, "date" : ISODate("2019-06-23"), "tempsC" : [ 4, 12, 17 ] }, { "_id" : 2, "date" : ISODate("2019-07-07"), "tempsC" : [ 14, 24, 11 ] }, { "_id" : 3, "date" : ISODate("2019-10-30"), "tempsC" : [ 18, 6, 8 ] } ] )
为了验证,查询集合
db.temperatures.find()
以下 db.collection.updateMany()
操作使用聚合管道来更新具有相应华氏温度的文档
db.temperatures.updateMany( { }, [ { $addFields: { "tempsF": { $map: { input: "$tempsC", as: "celsius", in: { $add: [ { $multiply: ["$$celsius", 9/5 ] }, 32 ] } } } } } ] )
具体来说,该管道包括一个 $addFields
阶段来添加一个新的数组字段 tempsF
,该字段包含华氏温度。要将 tempsC
数组中的每个摄氏温度转换为华氏温度,该阶段使用带有 $map
表达式、$add
和 $multiply
表达式的表达式。
为了验证更新,您可以查询集合
db.temperatures.find()
使用 let 变量更新
新版本5.0.
要定义您可以在命令的其他部分访问的变量,请使用 let 选项。
注意
要使用变量过滤结果,必须在 $expr
操作符内访问该变量。
创建一个 cakeFlavors
集合
db.cakeFlavors.insertMany( [ { _id: 1, flavor: "chocolate" }, { _id: 2, flavor: "strawberry" }, { _id: 3, flavor: "cherry" } ] )
以下 updateOne
命令使用 let
选项设置的变量
targetFlavor
变量设置为cherry
。该变量用于$eq
表达式中,以指定匹配过滤器。newFlavor
变量设置为orange
。该变量用于$set
操作符,以指定匹配文档的更新flavor
值。
db.cakeFlavors.updateOne( { $expr: { $eq: [ "$flavor", "$$targetFlavor" ] } }, [ { $set: { flavor: "$$newFlavor" } } ], { let: { targetFlavor: "cherry", newFlavor: "orange" } } )
运行前面的更新操作后,cakeFlavors
集合包含以下文档
[ { _id: 1, flavor: 'chocolate' }, { _id: 2, flavor: 'strawberry' }, { _id: 3, flavor: 'orange' } ]
附加示例
另请参阅各种更新方法页面以获取更多示例