Updates with Aggregation Pipeline使用聚合管道进行更新
Starting in MongoDB 4.2, you can use the aggregation pipeline for update operations. 从MongoDB 4.2开始,您可以使用聚合管道进行更新操作。With the update operations, the aggregation pipeline can consist of the following stages:通过更新操作,聚合管道可以由以下阶段组成:
Using the aggregation pipeline allows for a more expressive update statement, such as expressing conditional updates based on current field values or updating one field using the value of another field(s).使用聚合管道可以实现更具表达力的更新语句,例如基于当前字段值表达条件更新,或者使用另一个字段的值更新一个字段。
Example 实例1
Create an example 创建示例students collection (if the collection does not currently exist, insert operations will create the collection):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") }
] )
To verify, query the collection:若要验证,请查询集合:
db.students.find()
The following 以下db.collection.updateOne() operation uses an aggregation pipeline to update the document with _id: 3:db.collection.updateOne()操作使用聚合管道更新_id为3的文档:
db.students.updateOne( { _id: 3 }, [ { $set: { "test3": 98, modified: "$$NOW"} } ] )
Specifically, the pipeline consists of a 具体来说,管道由一个$set stage which adds the test3 field (and sets its value to 98) to the document and sets the modified field to the current datetime. The operation uses the aggregation variable NOW for the current datetime. To access the variable, prefix with $$ and enclose in quotes.$set阶段组成,它将test3字段(并将其值设置为98)添加到文档中,并将modified字段设置为当前日期时间。该操作将聚合变量NOW用于当前日期时间。若要访问该变量,请在前缀前加上$$并用引号括起来。
To verify the update, you can query the collection:若要验证更新,可以查询集合:
db.students.find().pretty()
Example 实例2
Create an example 创建一个示例students2 collection (if the collection does not currently exist, insert operations will create the collection):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") },
] )
To verify, query the collection:若要验证更新,可以查询集合:
db.students2.find()
The following 以下db.collection.updateMany() operation uses an aggregation pipeline to standardize the fields for the documents (i.e. documents in the collection should have the same fields) and update the modified field:db.collection.updateMany()操作使用聚合管道来标准化文档的字段(即集合中的文档应该具有相同的字段)并更新modified字段:
db.students2.updateMany( {},
[
{ $replaceRoot: { newRoot:
{ $mergeObjects: [ { quiz1: 0, quiz2: 0, test1: 0, test2: 0 }, "$$ROOT" ] }
} },
{ $set: { modified: "$$NOW"} }
]
)
Specifically, the pipeline consists of:具体而言,管道包括:
a带有$replaceRootstage with a$mergeObjectsexpression to set default values for thequiz1,quiz2,test1andtest2fields.$mergeObjects表达式的$replaceRoot阶段,用于设置quiz1、quiz2、test1和test2字段的默认值。The aggregation variable聚合变量ROOTrefers to the current document being modified.ROOT是指正在修改的当前文档。To access the variable, prefix with若要访问该变量,请在前缀前加上$$and enclose in quotes. The current document fields will override the default values.$$并用引号括起来。当前文档字段将覆盖默认值。a一个$setstage to update themodifiedfield to the current datetime.$set阶段,用于将modified字段更新为当前日期时间。The operation uses the aggregation variable该操作将聚合变量NOWfor the current datetime. To access the variable, prefix with$$and enclose in quotes.NOW用于当前日期时间。若要访问该变量,请在前缀前加上$$并用引号括起来。
To verify the update, you can query the collection:若要验证更新,可以查询集合:
db.students2.find()
Example 实例3
Create an example 创建一个示例students3 collection (if the collection does not currently exist, insert operations will create the collection):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") }
] );
To verify, query the collection:若要验证,可以查询集合:
db.students3.find()
The following 下面的db.collection.updateMany() operation uses an aggregation pipeline to update the documents with the calculated grade average and letter grade.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"
} } } }
]
)
Specifically, the pipeline consists of:具体而言,管道包括:
a$setstage to calculate the truncated average value of thetestsarray elements and to update themodifiedfield to the current datetime.$set阶段,用于计算tests数组元素的截断平均值,并将modified字段更新为当前日期时间。To calculate the truncated average, the stage uses the为了计算截断的平均值,该阶段使用$avgand$truncexpressions. The operation uses the aggregation variableNOWfor the current datetime. To access the variable, prefix with$$and enclose in quotes.$avg和$trunc表达式。该操作将聚合变量NOW用于当前日期时间。若要访问该变量,请在前缀前加上$$并用引号括起来。a一个$setstage to add thegradefield based on theaverageusing the$switchexpression.$set阶段,用于使用$switch表达式根据average添加grade字段。
To verify the update, you can query the collection:若要验证更新,可以查询集合:
db.students3.find()
Example 实例4
Create an example 创建一个示例students4 collection (if the collection does not currently exist, insert operations will create the collection):students4集合(如果该集合当前不存在,则插入操作将创建该集合):
db.students4.insertMany( [
{ "_id" : 1, "quizzes" : [ 4, 6, 7 ] },
{ "_id" : 2, "quizzes" : [ 5 ] },
{ "_id" : 3, "quizzes" : [ 10, 10, 10 ] }
] )
To verify, query the collection:若要验证,可以查询集合:
db.students4.find()
The following 以下db.collection.updateOne() operation uses an aggregation pipeline to add quiz scores to the document with _id: 2:db.collection.updateOne()操作使用聚合管道将测验分数添加到_id为2的文档中:
db.students4.updateOne( { _id: 2 },
[ { $set: { quizzes: { $concatArrays: [ "$quizzes", [ 8, 6 ] ] } } } ]
)
To verify the update, query the collection:若要验证更新,可以查询集合:
db.students4.find()
Example 实例5
Create an example 创建包含以摄氏度为单位的温度的示例temperatures collection that contains temperatures in Celsius (if the collection does not currently exist, insert operations will create the collection):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 ] }
] )
To verify, query the collection:若要验证,可以查询集合:
db.temperatures.find()
The following 以下db.collection.updateMany() operation uses an aggregation pipeline to update the documents with the corresponding temperatures in Fahrenheit:db.collection.updateMany()操作使用聚合管道来更新文档,使其具有以华氏度为单位的相应温度:
db.temperatures.updateMany( { },
[
{ $addFields: { "tempsF": {
$map: {
input: "$tempsC",
as: "celsius",
in: { $add: [ { $multiply: ["$$celsius", 9/5 ] }, 32 ] }
}
} } }
]
)
Specifically, the pipeline consists of an 具体来说,管道由$addFields stage to add a new array field tempsF that contains the temperatures in Fahrenheit. $addFields阶段组成,用于添加新的数组字段tempsF,该字段包含以华氏度为单位的温度。To convert each celsius temperature in the 要将tempsC array to Fahrenheit, the stage uses the $map expression with $add and $multiply expressions.tempsC数组中的每个摄氏度温度转换为华氏度,该阶段将$map表达式与$add和$multiply表达式一起使用。
To verify the update, you can query the collection:若要验证更新,可以查询集合:
db.temperatures.find()
Additional Examples其他示例
See also the various update method pages for additional examples:有关其他示例,请参阅各种更新方法页面: