Несколько операторов обновления mongo в одном заявлении?

Можно ли комбинировать $pushAll и $inc в одном выражении?

Перед объединением это прекрасно работает:

db.createCollection("test");
db.test.insert({"name" : "albert", "bugs" : []});

db.test.update({"name":"albert"}, 
    {"$pushAll" : {"bugs" : [{"name":"bug1", "count":1}]}});

db.test.update({"name":"albert"}, 
    {"$inc" : {"bugs.0.count" : 1}});

db.test.update({"name":"albert"}, 
    {"$pushAll" : {"bugs" : [{"name":"bug2", "count":1}]}});

Но когда я пытаюсь объединить его так:

db.createCollection("test");
db.test.insert({"name" : "albert", "bugs" : []});

db.test.update({"name":"albert"}, 
    {"$pushAll" : {"bugs" : [{"name":"bug1", "count":1}]}});

db.test.update({"name":"albert"}, 
    {
       "$pushAll" : {"bugs" : [{"name":"bug2", "count":1}]}, 
       "$inc" : {"bugs.0.count" : 1}
    }
);

Произошла эта ошибка:

have conflicting mods in update

Интересно, можно ли это сделать, а также, я думаю, что комбинировать больше, чем просто pushAll и inc, но я не уверен, поддерживается ли это или нет?


обновление марта 23, 2012

Я попробовал несколько $inc на разных элементах массива, и он работает (хотя и не корректно) из приведенного ниже ответа, чтобы выяснить, почему этот doensnt работает хорошо и что работает: The correct way to increment both fields is as follows: > db.test.update({"name":"albert"}, {"$inc" : {"bugs.0.count" : 1, "bugs.1.count" : 1}}):

db.test.update({"name":"albert"}, 
  {
    "$inc" : {"bugs.0.count" : 1}, 
    "$inc" : {"bugs.1.count" : 1}
  }
);

И эта комбинация $set и $inc на разных элементах массива также работает:

db.test.update({"name":"albert"}, 
  {
    "$set" : {"bugs.0.test" : {"name" : "haha"}}, 
    "$inc" : {"bugs.0.count" : 1}, 
    "$inc" : {"bugs.1.count" : 1}
  }
);

Но объедините любой из них с помощью $push или $pushAll, все пойдет на ошибку.

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

Ответ 1

Несколько обновлений могут быть выполнены в том же документе, если эти обновления не конфликтуют (следовательно, ошибка "иметь конфликтующие моды при обновлении" ).

Потому что "$ push": { "bugs": [{ "name": "bug1", "count": 1}]} и "$ inc": { "bugs.0.count": 1} оба пытаются изменить одну и ту же часть документа (а именно массив "ошибок" ), они конфликтуют.

Несколько обновлений могут быть объединены, если каждый влияет на другую часть документа:

например:

> db.test.drop()
true
> db.test.save({ "_id" : 1, "name" : "albert", "bugs" : [ ] })
> db.test.update({"name":"albert"}, {"$pushAll" : {"bugs" : [{"name":"bug1", "count":1}]}, "$inc" : {"increment" : 1}, $set:{"note":"Here is another field."}})
> db.test.find()
{ "_id" : 1, "bugs" : [ { "name" : "bug1", "count" : 1 } ], "increment" : 1, "name" : "albert", "note" : "Here is another field." }
> 

Обновление содержало три разных операции ($ pushAll, $inc и $set), но было успешно завершено, потому что каждая операция затрагивала другую часть документа.

Я понимаю, что это не совсем то, что вы надеялись сделать, но, надеюсь, это поможет вам немного лучше понять, как работают обновления, и, возможно, представить некоторые идеи о том, как ваши обновления и/или документы могут быть реструктурированы для выполнения которые требуется вашему приложению. Удачи.