Mongodb обновить конкретный элемент из подмассива - PullRequest
12 голосов
/ 12 февраля 2012

У меня есть коллекция со следующей схемой:

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

Мне нужно обновить один из элементов в массиве в документе с помощью _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")
  }
})

Итак, я хочу обновить конкретный элемент из массива: и, насколько можно видеть, это четвертый элемент. Проблема в том, что при выполнении запроса он, скорее всего, обновляет первый элемент.

Как я могу это исправить?

1 Ответ

23 голосов
/ 12 февраля 2012

Проблема в вашем коде - 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")
  }
})

и вывод

    {
        "a" : ObjectId("4ef85a3e46b3b84408000000"),
        "c" : 28,
        "p" : [
            ObjectId("4f00631046b3b85002000000"),
            ObjectId("4b97e62bf1d8c7152c9ccb74")
        ],
        "t" : ISODate("2013-05-13T14:22:46.777Z"),
        "u" : 26
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...