To perform update operations, you can use the aggregation pipeline. 要执行更新操作,可以使用聚合管道。You can build and execute aggregation pipelines to perform updates in MongoDB Atlas, MongoDB Compass, MongoDB Shell, or Drivers.您可以构建和执行聚合管道,以在MongoDB Atlas、MongoDB Compass、MongoDB Shell或驱动程度中执行更新。
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).使用聚合管道允许更具表现力的更新语句,例如基于当前字段值表示条件更新,或使用另一个字段的值更新一个字段。
Note
Dollar Characters in Field Values字段值中的美元字符
When you use an aggregation pipeline, sanitize any strings that are passed from user input or created dynamically from parsing data. 使用聚合管道时,对从用户输入传递或从解析数据动态创建的任何字符串进行清理。If any field values are literal string values and start with a dollar character, the value must be passed to the 如果任何字段值都是文字字符串值并且以美元字符开头,则必须将该值传递给$literal aggregation operator. $literal聚合运算符。The following example demonstrates using the aggregation pipeline 以下示例演示了如何使用聚合管道$set and the $literal operator to update the document with an _id of 1 to have a cost field of $27.$set和$literal运算符将_id为1的文档更新为cost(成本)字段$27。
db.inventory.updateOne( { _id: 1 }, [ { $set: { "cost": { $literal: "$27" } } } ] )Create an Update Aggregation Pipeline in Atlas在Atlas中创建更新聚合管道
You can use the MongoDB Atlas UI to build an aggregation pipeline to perform updates. 您可以使用MongoDB Atlas UI构建聚合管道来执行更新。To create and execute aggregation pipelines in the MongoDB Atlas UI, you must have the 要在MongoDB Atlas UI中创建和执行聚合管道,您必须具有项目数据访问只读角色或更高级别。Project Data Access Read Only role or higher.
Access the Aggregation Pipeline Builder.访问聚合管道生成器。
Select the database for the collection.选择集合的数据库。The main panel and Namespaces on the left side list the collections in the database.主面板和左侧的命名空间列出了数据库中的集合。Select the collection.选择集合。Select the collection on the left-hand side or in the main panel. The main panel displays the Find, Indexes, and Aggregation views.在左侧或主面板中选择集合。主面板显示“查找”、“索引”和“聚合”视图。Select the Aggregation view.选择聚合视图。When you first open the Aggregation view, Atlas displays an empty aggregation pipeline.当您第一次打开“聚合”视图时,Atlas会显示一个空的聚合管道。
Create an aggregation pipeline to perform updates.创建聚合管道以执行更新。
Select an aggregation stage.选择聚合阶段。Select an aggregation stage from the Select drop-down menu in the bottom-left panel.从左下角面板的“选择”下拉菜单中选择聚合阶段。The toggle to the right of the drop-down menu dictates whether the stage is enabled.下拉菜单右侧的开关指示是否启用该阶段。To perform updates with an aggregation, use one of these stages:要使用聚合执行更新,请使用以下阶段之一:Fill in your aggregation stage.填写聚合阶段。Fill in your stage with the appropriate values. If Comment Mode is enabled, the pipeline builder provides syntactic guidelines for your selected stage.用适当的值填充阶段。如果启用了注释模式,管道构建器将为您选择的阶段提供语法指南。As you modify your stage, Atlas updates the preview documents on the right based on the results of the current stage.当您修改阶段时,Atlas会根据当前阶段的结果更新右侧的预览文档。For examples of what you might include in your aggregation stage, see the examples on this page.有关聚合阶段可能包含的内容的示例,请参阅本页上的示例。Add stages as needed. For more information on creating aggregation pipelines in Atlas, refer to Create an Aggregation Pipeline.根据需要添加阶段。有关在Atlas中创建聚合管道的更多信息,请参阅创建聚合管道。
Export the aggregation pipeline.导出聚合管道。
Click Export to Language.单击导出到语言。You can find this button at the top of the pipeline builder.您可以在管道生成器的顶部找到此按钮。Select your desired export language.选择所需的导出语言。In the Export Pipeline To menu, select your desired language.在“导出管道到”菜单中,选择所需的语言。The My Pipeline pane on the left displays your pipeline in MongoDB Shell syntax. You can copy this directly to execute your pipeline in the MongoDB Shell.左侧的My Pipeline窗格以MongoDB Shell语法显示管道。您可以直接复制它以在MongoDB Shell中执行管道。The pane on the right displays your pipeline in the selected language. Select your preferred language.右侧窗格以所选语言显示管道。选择首选语言。Select options, if desired.如果需要,请选择选项。(Optional)(可选): Check the Include Import Statements option to include the required import statements for the language selected.:选中“包含导入语句”选项,以包含所选语言所需的导入语句。(Optional)(可选): Check the Include Driver Syntax option to include Driver-specific code to::选中“包含驱动程序语法”选项,以包含特定于驱动程序的代码:Initialize the client初始化客户端Specify the database and collection指定数据库和集合Perform the aggregation operation执行聚合操作
Copy the pipeline.复制管道。Click the Copy button at the top-right of the pipeline to copy the pipeline for the selected language to your clipboard. Paste the copied pipeline into your application.单击管道右上角的“复制”按钮,将所选语言的管道复制到剪贴板。将复制的管道粘贴到应用程序中。
Examples示例
The following examples demonstrate how to use the aggregation pipeline stages 以下示例演示了如何使用聚合管道阶段$set, $replaceRoot, and $addFields to perform updates.$set、$replaceRoot和$addFields执行更新。
updateOne with 配合$set
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. $set阶段组成,该阶段将test3字段(并将其值设置为98)添加到文档中,并将modified字段设置为当前日期时间。The operation uses the aggregation variable 该操作使用聚合变量NOW for the current datetime. NOW作为当前日期时间。To access the variable, prefix with 要访问该变量,请在前面加上$$ and enclose in quotes.$$并将其括在引号中。
To verify the update, you can query the collection:要验证更新,您可以查询集合:
db.students.find().pretty()updateMany with 配合$replaceRoot and 和$set
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.$replaceRoot阶段,配合$mergeObjects表达式,用于为quiz1、quiz2、test1和test2字段设置默认值。The aggregation variable聚合变量ROOTrefers to the current document being modified. To access the variable, prefix with$$and enclose in quotes. The current document fields will override the default values.ROOT是指正在修改的当前文档。要访问该变量,请在前面加上$$并将其括在引号中。当前文档字段将覆盖默认值。a$setstage to update themodifiedfield to the current datetime. The operation uses the aggregation variableNOWfor the current datetime. To access the variable, prefix with$$and enclose in quotes.$set阶段,用于将modified字段更新为当前日期时间。该操作使用聚合变量NOW作为当前日期时间。要访问该变量,请在前面加上$$并将其括在引号中。
To verify the update, you can query the collection:要验证更新,您可以查询集合:
db.students2.find()updateMany with 配合$set
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.$avg和$trunc表达式。The operation uses the aggregation variable该操作使用聚合变量NOWfor the current datetime.NOW作为当前日期时间。To access the variable, prefix with要访问该变量,请在前面加上$$and enclose in quotes.$$并将其括在引号中。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()updateOne with 配合$set
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()updateMany with 配合$addFields
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()Update with let Variables使用let变量进行更新
New in version 5.0.在版本5.0中新增。
To define variables that you can access elsewhere in the command, use the let option.要定义可以在命令的其他地方访问的变量,请使用let选项。
Note
Create a collection 创建一个系列cakeFlavors:cakeFlavors:
db.cakeFlavors.insertMany( [
{ _id: 1, flavor: "chocolate" },
{ _id: 2, flavor: "strawberry" },
{ _id: 3, flavor: "cherry" }
] )
The following 以下updateOne command uses variables set with the let option:updateOne命令使用用let选项设置的变量:
ThetargetFlavorvariable is set tocherry. This variable is used in the$eqexpression to specify the match filter.targetFlavor变量设置为cherry。此变量在$eq表达式中用于指定匹配筛选器。ThenewFlavorvariable is set toorange. This variable is used in the$setoperator to specify the updatedflavorvalue for the matched document.newFlavor变量设置为orange。此变量在$set运算符中用于指定匹配文档的更新flavor值。
db.cakeFlavors.updateOne(
{
$expr: { $eq: [ "$flavor", "$$targetFlavor" ] }
},
[
{
$set: { flavor: "$$newFlavor" }
}
],
{
let: { targetFlavor: "cherry", newFlavor: "orange" }
}
)
After you run the preceding update operation, the 运行上述更新操作后,cakeFlavors collection contains these documents:cakeLavors集合包含以下文档:
[
{ _id: 1, flavor: 'chocolate' },
{ _id: 2, flavor: 'strawberry' },
{ _id: 3, flavor: 'orange' }
]Additional Examples其他示例
See also the various update method pages for additional examples:其他示例请参见各种更新方法页面: