Alex Rivera | Logout

Mongodb update the specific element from subarray

Asked 2012-02-12T06:45:53.910
12

I have a collection with a following schema:

{
  "_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
    }]
}

I need to update one of the elements in the array in the document with _id = 28 but only if the a = to some value and c = some value

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")
  }
})

So basically I want to update specific element from array: and as far as one can see, this is the fourth element. The problem is that when the query is executing, it most likely updates the first element.

How can I fix it?

Edit
Report

1 Answer

23

The problem in your code is dot-notation because When you specify the dot notation you assume that the filter criterias specified must match the single array element that satisfies all the criteria. But it doesnt. Dot notation on arrays may pickup any array element if any single criteria matches. Thats why you are getting the unexpected update.

You have to use $elemMatch to match all the filters in the array element.

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")
  }
})

and the output is

    {
        "a" : ObjectId("4ef85a3e46b3b84408000000"),
        "c" : 28,
        "p" : [
            ObjectId("4f00631046b3b85002000000"),
            ObjectId("4b97e62bf1d8c7152c9ccb74")
        ],
        "t" : ISODate("2013-05-13T14:22:46.777Z"),
        "u" : 26
    }
answered 2012-02-12T07:27:39.663

Your Answer