您可以将位置运算符与MongoDB查询语言 (MQL) 结合使用来 更新包含数组的文档,而无需替换大量或向数组追加内容。
本教程介绍了MongoDB中位置操作符的几个用例。
开始之前
安装 mongosh。
连接到部署。
使用
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 } ] } ] );
步骤
以下示例展示了如何:
使用 $ 操作符更新数组中的第一个匹配项
要仅更新大量中的第一个匹配项,请使用 $
操作符。$
操作符充当占位符,以更新第一个匹配的元素。
以下示例使用 updateOne()
方法以及 $
和 $set
操作符将 engineering
大量中第一封具有值 missingEmail
的电子邮件更新为 alice@mail.com
。
1 db.employees.updateOne( 2 { "engineering.email": "missingEmail" }, 3 { "$set": { "engineering.$.email": "alice@mail.com" } } 4 );
使用 find()
方法确认对爱丽丝电子邮件的更新。
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 } ] } ]
如上示例所示,过滤具有 engineering.email
字段设立为 missingEmail
的大量元素的文档后,$
操作符仅更新与过滤匹配的第一个匹配项。
使用 $ 操作符和 $elemMatch 更新特定元素
要更新特定元素,可以使用 $elemMatch
操作符。
以下示例使用$elemMatch
操作符和$
操作符将 Bob 的 email
更新为 "bob@mail.com"
。
1 db.employees.updateOne( 2 { engineering: { $elemMatch: { name: "Bob", email: "missingEmail" } } }, 3 { $set: { "engineering.$.email": "bob@mail.com" } } 4 );
使用 find()
方法确认对 Bob电子邮件的更新。
db.employees.find( { "engineering": { $elemMatch: { name: "Bob" } } }, { "engineering.$": 1, _id: 0 } );
[ { engineering: [ { name: 'Bob', email: 'bob@mail.com', salary: 75000 } ] } ]
使用 $[] 操作符更新文档中的所有数组元素
要通过单个操作更新大量的每个元素,请使用 $[]
操作符。
假设您想向纽约市的销售员工额外发放 2,000 美元的奖金。您可以使用带有updateMany()
$[]
操作符和$inc
bonus
操作符的sales
方法,将NYC
文档的 大量内的所有 字段增加2000
。
1 db.employees.updateMany( 2 { "_id": "NYC" }, 3 { "$inc": { "sales.$[].bonus": 2000 } } 4 );
使用 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 } ] } ]
使用 $[<identifier>] 操作符更新与筛选条件匹配的元素
要在单个操作中更新多个大量元素,而不需要与替换操作搭配使用过多的客户端代码,请使用 $[<identifier>]
操作符。$[<identifier>]
操作符充当占位符,以更新与 arrayFilters 条件匹配的所有元素。
假设您希望在特定员工满足多个条件时更新其工资。您可以使用 updateMany()
方法和 $[<identifier>]
操作符来完成此任务。
1 db.employees.updateMany( 2 {}, 3 { 4 "$set": { 5 "engineering.$[elemX].salary": 95000, 6 "sales.$[elemY].salary": 75000 7 } 8 }, 9 { 10 "arrayFilters": [ 11 { "elemX.name": "Bob", "elemX.salary": 75000 }, 12 { "elemY.name": "Ed", "elemY.salary": 50000, } 13 ] 14 } 15 );
在上面的示例中,第一个参数是空匹配项,用于评估集合中的所有文档。
elemX
和 elemY
代表两个不同的 arrayFilter:
要匹配
elemX
,大量对象的name
字段必须为Bob
,salary
必须为75000
。要匹配
elemY
,大量对象的name
字段必须为Ed
,salary
必须为50000
。
如果文档中的大量项与 elemX
过滤匹配,则 updateMany()
会将该对象的 salary
字段设置为 95000
。如果大量项与 elemY
过滤匹配,则 updateMany()
会将该对象的 salary
字段设置为 75000
。如果过滤不匹配,则不会触发相应的 $set
操作。
使用 find()
方法确认对 Bob 工资的更新,因为他满足 elemX
的两个条件。
db.employees.find( { "engineering.name": "Bob" }, { engineering: { $elemMatch: { name: "Bob" } }, _id: 0 } );
[ { engineering: [ { name: "Bob", email: "bob@mail.com", salary: 95000 } ] } ]
使用 find()
方法确认对 Ed 工资的更新未成功,因为他不满足 elemX
或 elemY
的条件。
db.employees.find( { "sales.name": "Ed" }, { sales: { $elemMatch: { name: "Ed" } }, _id: 0 } );
[ { sales: [ { name: "Ed", email: "ed@mail.com", salary: 99000, bonus: 4000 } ] } ]
结论
本教程将向您介绍MongoDB查询语言 (MQL) 中的一些位置操作符。这些操作符在处理数组时非常有用,因为它们使您不必对大量进行完全替换或扩展客户端操作。要学习;了解有关MQL 的更多信息,请参阅Atlas入门。
要学习;了解有关MongoDB中更新操作符的更多信息,请参阅更新操作符。