Несколько операторов обновления 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), но было успешно завершено, потому что каждая операция затрагивала другую часть документа.
Я понимаю, что это не совсем то, что вы надеялись сделать, но, надеюсь, это поможет вам немного лучше понять, как работают обновления, и, возможно, представить некоторые идеи о том, как ваши обновления и/или документы могут быть реструктурированы для выполнения которые требуется вашему приложению. Удачи.