Mongodb更新子阵列中的特定元素

Sal*_*ali 12 mongodb

我有一个具有以下架构的集合:

{
  "_id" : 28,
  "n" : [{
      "a" : ObjectId("4ef8466e46b3b8140e000000"),
      "c" : 28,
      "p" : [ObjectId("4f00640646b3b88005000003"), ObjectId("4f00640146b3b88005000002"), ObjectId("4f00637d46b3b8cc0e000001"), ObjectId("4f00638046b3b8cc0e000002"), ObjectId("4f00638246b3b8cc0e000003"), ObjectId("4f00631646b3b85002000001"), ObjectId("4f00631846b3b85002000002")],
      "u" : 26
    }, {
      "a" : ObjectId("4ef8466e46b3b8140e000000"),
      "c" : 10,
      "p" : [ObjectId("4f00640146b3b88005000002"), ObjectId("4f0063fd46b3b88005000001")],
      "u" : 26
    }, {
      "a" : ObjectId("4ef8467846b3b8780d000001"),
      "u" : 26,
      "p" : [ObjectId("4f00637b46b3b8cc0e000000")],
      "c" : 28
    }, {
      "a" : ObjectId("4ef85a3e46b3b84408000000"),
      "u" : 26,
      "p" : [ObjectId("4f00631046b3b85002000000")],
      "c" : 28
    }]
}
Run Code Online (Sandbox Code Playgroud)

我需要使用_id = 28更新文档中数组中的一个元素,但前提是a =某个值且c =某个值

db.coll.update({
'_id' : 28,
'n.a' : new ObjectId('4ef85a3e46b3b84408000000'),
'n.c' : 28
},
{
  $push : {
     'n.$.p' : ObjectId("4b97e62bf1d8c7152c9ccb74")
  },
  $set : {
     'n.$.t' : ISODate("2013-05-13T14:22:46.777Z")
  }
})
Run Code Online (Sandbox Code Playgroud)

所以基本上我想更新数组中的特定元素:据我们所知,这是第四个元素.问题是,当查询执行时,它很可能更新第一个元素.

我该如何解决?

Ram*_*Vel 23

代码中的问题是dot-notation因为当您指定点表示法时,您假定指定的过滤器标准必须与满足所有条件的单个数组元素匹配.但它没有.如果任何单个条件匹配,则数组上的点表示法可以拾取任何数组元素.这就是为什么你得到意想不到的更新.

您必须使用$elemMatch匹配array元素中的所有过滤器.

db.coll.update({
'_id' : 28,
n: { 
   $elemMatch:{
       a : new ObjectId('4ef85a3e46b3b84408000000'),
       c : 28 }
   }
},
{
  $push : {
     'n.$.p' : ObjectId("4b97e62bf1d8c7152c9ccb74")
  },
  $set : {
     'n.$.t' : ISODate("2013-05-13T14:22:46.777Z")
  }
})
Run Code Online (Sandbox Code Playgroud)

而输出是

    {
        "a" : ObjectId("4ef85a3e46b3b84408000000"),
        "c" : 28,
        "p" : [
            ObjectId("4f00631046b3b85002000000"),
            ObjectId("4b97e62bf1d8c7152c9ccb74")
        ],
        "t" : ISODate("2013-05-13T14:22:46.777Z"),
        "u" : 26
    }
Run Code Online (Sandbox Code Playgroud)