multiple mongo update operator in a single stateme

2019-01-11 11:15发布

问题:

Can i combine $pushAll and $inc in one statement ?

Before combine, this works fine :

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}]}});

But when i try combining it like this :

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

This error happens :

have conflicting mods in update

I wonder it is possible to do this, and also, i imagine combining more than just pushAll and inc, but i am not sure whether this is supported or not ?


update march 23, 2012

I tried multiple $inc on different elements of an array, and it works (although not correctly. quoted from the answer below to clarify why this doensnt work well and what works : 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}
  }
);

And this combination of $set and $inc on different elements of an array also works :

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

But combine any of these with $push or $pushAll, all will go error.

So, my current conclusion is, it is not about multiple operations on multiple elements within the same array which is the problem, but combining these operations with $push or $pushAll that can change the the array is the problem.

回答1:

Multiple updates may be performed on the same document, as long as those updates do not conflict (hence the "have conflicting mods in update" error).

Because "$push" : {"bugs" : [{"name":"bug1", "count":1}]} and "$inc" : {"bugs.0.count" : 1} are both attempting to modify the same portion of the document (namely the "bugs" array), they conflict.

Multiple updates may be combined if each affects a different part of the document:

for example:

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

The update contained three different operations ($pushAll, $inc, and $set), but was able to complete successfully, because each operation affected a different part of the document.

I realize this is not exactly what you were hoping to do, but hopefully it will provide you with a little better understanding of how updates work, and perhaps provide some ideas how your updates and/or documents may be restructured to perform the functionality that your application requires. Good luck.



标签: mongodb