Database Manual / CRUD Operations / Update

Update Array Elements in a Document with MQL Positional Operators使用MQL位置运算符更新文档中的数组元素

You can use positional operators with MongoDB Query Language (MQL) to update documents that contain arrays without replacing the array or appending to it.您可以在MongoDB查询语言(MQL)中使用位置运算符来更新包含数组的文档,而无需替换数组或附加数组。

This tutorial presents several use cases for positional operators within MongoDB.本教程介绍了MongoDB中位置运算符的几个用例。

Before You Begin开始之前

  • Install mongosh.安装mongosh
  • Connect to a deployment.连接到部署
  • Use mongosh to insert documents into a new collection in the default test database:使用mongosh将文档插入到默认test数据库中的新集合中:

    db.employees.insertMany(
    [
    {
    _id: 'SF',
    engineering: [
    { name: 'Alice', email: 'missingEmail', salary: 100000 },
    { name: 'Bob', email: 'missingEmail', salary: 75000 }
    ],
    sales: [
    { name: 'Charlie', email: 'charlie@mail.com', salary: 90000, bonus: 1000 }
    ]
    },
    {
    _id: 'NYC',
    engineering: [
    { name: 'Dave', email: 'dave@mail.com', salary: 55000 },
    ],
    sales: [
    { name: 'Ed', email: 'ed@mail.com', salary: 99000, bonus: 2000 },
    { name: 'Fran', email: 'fran@mail.com', salary: 50000, bonus: 10000 }
    ]
    }
    ]
    );

Steps步骤

The following examples show you how to:以下示例向您展示了如何:

Use the $ Operator to Update the First Match in an Array使用$运算符更新数组中的第一个匹配项

To update only the first match within an array, use the $ operator. 要仅更新数组中的第一个匹配项,请使用$运算符。The $ operator acts as a placeholder to update the first element matched.$运算符充当占位符,用于更新匹配的第一个元素。

The following example uses the updateOne() method with the $ and $set operators to update the first email that has the value missingEmail in the engineering array to alice@mail.com.以下示例使用带有$$set运算符的updateOne()方法将engineering数组中具有missingEmail值的第一封电子邮件更新为alice@mail.com

db.employees.updateOne(
{ "engineering.email": "missingEmail" },
{ "$set": { "engineering.$.email": "alice@mail.com" } }
);

Use the find() method to confirm the update to Alice's email.使用find()方法确认对Alice电子邮件的更新。

   db.employees.find()
[
{
_id: 'SF',
engineering: [
{ name: 'Alice', email: 'alice@mail.com', salary: 100000 },
{ name: 'Bob', email: 'missingEmail', salary: 75000 }
],
sales: [
{ name: 'Charlie', email: 'charlie@mail.com', salary: 90000, bonus: 1000 }
]
},
{
_id: 'NYC',
engineering: [
{ name: 'Dave', email: 'dave@mail.com', salary: 55000 }
],
sales: [
{ name: 'Ed', email: 'ed@mail.com', salary: 99000, bonus: 2000 },
{ name: 'Fran', email: 'fran@mail.com', salary: 50000, bonus: 10000 }
]
}
]

As shown in the example above, after you filter for documents that have an array element with the engineering.email field set to missingEmail, the $ operator only updates the first occurrence that matches the filter.如上例所示,在筛选出具有engineering.email字段设置为missingEmail的数组元素的文档后,$运算符仅更新与筛选器匹配的第一个匹配项。

Use the $ Operator with $elemMatch to Update a Specific Element使用$运算符和$elemMatch来更新特定元素

To update a particular element, you can use the $elemMatch operator.要更新特定元素,可以使用$elemMatch运算符。

The following example uses the $elemMatch operator and the $ operator to update Bob's email to "bob@mail.com".以下示例使用$elemMatch运算符和$运算符将Bob的email更新为"bob@mail.com"

db.employees.updateOne(
{ engineering: { $elemMatch: { name: "Bob", email: "missingEmail" } } },
{ $set: { "engineering.$.email": "bob@mail.com" } }
);

Use the find() method to confirm the update to Bob's email.使用find()方法确认对Bob电子邮件的更新。

db.employees.find(
{ "engineering": { $elemMatch: { name: "Bob" } } },
{ "engineering.$": 1, _id: 0 }
);
[
{
engineering: [ { name: 'Bob', email: 'bob@mail.com', salary: 75000 } ]
}
]

Use the $[] Operator to Update All Array Elements Within a Document使用$[]运算符更新文档中的所有数组元素

To update every element of an array with a single operation, use the $[] operator.要使用单个操作更新数组的每个元素,请使用$[]运算符。

Consider a case where you want to give an additional bonus of $2,000 to your sales employees in NYC. You can use the updateMany() method with the $[] operator and the $inc operator to increase all bonus fields within the sales array in the NYC document by 2000.考虑一个案例,你想给纽约市的销售员工额外发放2000美元的奖金。您可以将updateMany()方法配合$[]运算符和$inc运算符一起使用,以将NYC文档中sales数组中的所有bonus(奖金)字段增加2000

db.employees.updateMany(
{ "_id": "NYC" },
{ "$inc": { "sales.$[].bonus": 2000 } }
);

Use the find() method to confirm the update to the bonus fields for the employees on NYC's sales team.使用find()方法确认对NYC销售团队员工bonus字段的更新。

db.employees.find(
{ _id: "NYC" },
{ sales: 1, _id: 0 }
);
[
{
sales: [
{ name: 'Ed', email: 'ed@mail.com', salary: 99000, bonus: 4000 },
{ name: 'Fran', email: 'fran@mail.com', salary: 50000, bonus: 12000 }
]
}
]

Use the $[<identifier>] Operator to Update Elements that Match a Filter Condition使用$[<identifier>]运算符更新与筛选条件匹配的元素

To update several array elements in a single operation without excessive client-side code paired with a replace operation, use the $[<identifier>] operator. 要在单个操作中更新多个数组元素,而不需要与替换操作配对过多的客户端代码,请使用$[<identifier>]运算符。The $[<identifier>] operator acts as a placeholder to update all elements that match an arrayFilters condition.$[<identifier>]运算符充当占位符,用于更新与arrayFilters条件匹配的所有元素。

Consider a case where you want to update specific employees' salaries if they meet a number of conditions. You can use the updateMany() method with the $[<identifier>] operator to accomplish this task.考虑一个案例,如果特定员工满足一些条件,你想更新他们的工资。您可以使用updateMany()方法配合$[<identifier>]运算符来完成此任务。

db.employees.updateMany(
{},
{
"$set": {
"engineering.$[elemX].salary": 95000,
"sales.$[elemY].salary": 75000
}
},
{
"arrayFilters": [
{ "elemX.name": "Bob", "elemX.salary": 75000 },
{ "elemY.name": "Ed", "elemY.salary": 50000, }
]
}
);

In the above example, the first parameter is an empty match, to evaluate all documents in the collection.在上面的示例中,第一个参数是空匹配,用于计算集合中的所有文档。

elemX and elemY represent two different arrayFilters:elemXelemY表示两个不同的arrayFilters

  • To match elemX, an array object must have a name field of Bob and a salary of 75000.为了匹配elemX,数组对象必须具有name字段为Bob75000字段为salary
  • To match elemY, an array object must have a name field of Ed and a salary of 50000.为了匹配elemY,数组对象必须具有name字段为Edsalary字段为50000

If an array item in the document matches the elemX filter, then updateMany() sets the salary field for the object to 95000. 如果文档中的数组项与elemX筛选器匹配,则updateMany()将对象的工资字段设置为95000If an array item matches the elemY filter, then updateMany() sets the salary field for the object to 75000. 如果数组项与elemY筛选器匹配,则updateMany()将对象的salary字段设置为75000If a filter doesn't match, the corresponding $set operation doesn't trigger.如果筛选器不匹配,则相应的$set操作不会触发。

Use the find() method to confirm the update to Bob's salary because he meets both elemX's conditions.使用find()方法确认Bob的工资更新,因为他满足elemX的两个条件。

db.employees.find(
{ "engineering.name": "Bob" },
{ engineering: { $elemMatch: { name: "Bob" } }, _id: 0 }
);
[
{
engineering: [
{ name: "Bob", email: "bob@mail.com", salary: 95000 }
]
}
]

Use the find() method to confirm the update to Ed's salary did not succeed because he does not meet either elemX or elemY's conditions.使用find()方法确认Ed的工资更新没有成功,因为他不符合elemXelemY的条件。

db.employees.find(
{ "sales.name": "Ed" },
{ sales: { $elemMatch: { name: "Ed" } }, _id: 0 }
);
[
{
sales: [
{ name: "Ed", email: "ed@mail.com", salary: 99000, bonus: 4000 }
]
}
]

Conclusion结论

This tutorial teaches you some of the positional operators within the MongoDB Query Language (MQL). These operators are useful when working with arrays because they prevent you from having to do full replaces on the array or extended client-side manipulation. 本教程将教您MongoDB查询语言(MQL)中的一些位置运算符。这些运算符在处理数组时非常有用,因为它们可以防止您对数组进行完全替换或扩展客户端操作。To learn more about MQL, see get started with Atlas.要了解有关MQL的更多信息,请参阅Atlas入门

To learn more about update operators in MongoDB, see Update Operators.要了解有关MongoDB中更新运算符的更多信息,请参阅更新运算符