несколько операторов монго в одном выражении? - PullRequest
14 голосов
/ 22 марта 2012

Могу ли я объединить $ 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 Ответ

21 голосов
/ 22 марта 2012

Множественные обновления могут выполняться для одного и того же документа, если эти обновления не конфликтуют (следовательно, возникает ошибка «есть конфликтующие моды в обновлении»).

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...