Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
742 views
in Technique[技术] by (71.8m points)

mongodb - multiple mongo update operator in a single statement?

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...