MongoDB在嵌套字段中更新数据

all*_*ang 44 nested mongodb

我使用Mongo作为我的数据库.我有一个数据:

 {
   _id : '123'
   friends: [
     {name: 'allen', emails: [{email: '11111', using: 'true'}]}
   ]
 }
Run Code Online (Sandbox Code Playgroud)

现在,我想动机用户的朋友的电子邮件'的电子邮件,其_id是'123',我这样写:

db.users.update ({_id: '123'}, {$set: {"friends.0.emails.$.email" : '2222'} })
Run Code Online (Sandbox Code Playgroud)

这很简单,但是,当电子邮件数组有两个或更多数据时,这是错误的.所以,我的问题是:如何在嵌套文件中激活数据---只有两个或更多嵌套数组?谢谢.

Cri*_*scu 76

您需要为数组使用Dot Notation.

也就是说,您应该替换$您尝试更新的元素的从零开始的索引.

例如:

db.users.update ({_id: '123'}, { '$set': {"friends.0.emails.0.email" : '2222'} });
Run Code Online (Sandbox Code Playgroud)

将更新第一个朋友的第一封电子邮件,和

db.users.update ({_id: '123'}, { '$set': {"friends.0.emails.1.email" : '2222'} })
Run Code Online (Sandbox Code Playgroud)

将更新第一位朋友的第二封电子邮件.


Kan*_*bel 8

更新多级数组的一种灵活方法是使用arrayFilters,它允许查询索引并将其分配给标识符。

db.collection.update(
   { <query selector> },
   { <update operator>: { "array.$[<identifier>].field" : value } },
   { arrayFilters: [ { <identifier>: <condition> } } ] }
)
Run Code Online (Sandbox Code Playgroud)

以下是您提供的示例以及一位新朋友的两封电子邮件:

{
   _id : '123'
   friends: [
     {name: 'allen', emails: [
        {email: '11111', using: 'true'}
     ]},
     {name: 'lucy' , emails: [
        {email: 'lucy@work.com', using:'true'}, 
        {email:'lucyGucy@zmail.com', using : 'false'}
     ]}
   ]
 }
Run Code Online (Sandbox Code Playgroud)

假设 lucyGucy@zmail.com 正在更新为 lucy.is.gucy@zmail.com。我们可以使用数组过滤器中的nameemail字段来标识我们要更新的索引。

db.users.update({_id:123}, {$set:{
    "friends.$[updateFriend].emails.$[updateEmail].email : "lucy.is.gucy@zmail.com"
}}, {
    "arrayFilters": [
      {"updateFriend.name" : "lucy"},
      {"updateEmail.email" : "lucyGucy@zmail.com"}
    ]
})
Run Code Online (Sandbox Code Playgroud)

通过这种方式,更新对特定的数组顺序不敏感。上面的示例使用了两个标识符updateFriendupdateEmail,它们将匹配 - 对于它们所应用的数组 - 满足数组过滤条件的任何元素。如文档中所述:

<identifier> 必须以小写字母开头并且仅包含字母数字字符。

此外,虽然电子邮件可能是唯一的,但我建议在所有子文档中包含一个唯一的 id,以便 arrayFilters 可以是准确的。