javascript - MongoDB, conditional upserts or updates - Stack Overflow

When using MongoDB I'm currently doing a conditional upsert as a part of an aggregation process, o

When using MongoDB I'm currently doing a conditional upsert as a part of an aggregation process, on the form (simplified alot):

db.dbname.update({attr1 : value1, attr2 : value2},
                 {"$inc" : { avg : current_value, nr : 1}},
                 false (multi), true (upsert))

But I want to able to keep a maximum (and minimum) value as well, without having to retrieve the document. Something along the lines of:

db.dbname.update({ attr1 : value1, attr2 : value2},
                 {"$inc" : { avg : current_value, nr : 1},
                  "$setIfBigger" : { max : current_value}},
                 false (multi), true (upsert))

Is this possible in an efficient way?

My current, extremely inefficient, solution is that I check for a current aggregation document, and if it exists I update the values accordingly, and if it doesn't I create a new document. Example (again, simplified alot, but the essence is there):

var obj = db.dbname.findOne({attr1 : value1, attr2 : value2},{_id:1});
if (obj != null) {
   db.dbname.update({attr1 : value1, attr2 : value2},
                    {"$inc" : { avg : current_value, nr : 1},
                     "$set" : { max : (obj.max > current_value ? obj.max : current_value}},
                    false (multi), true (upsert));
} else {
   db.dbname.save({attr1 : value1, attr2 : value2, 
                   avg : current_value, nr : 1,
                   max : current_value});
}

The actual program is written in Java and uses the mongo-API, and the aggregation process is quite complex and uses composition techniques way beyond Javascript to communicate with other servers, ergo mapreduce is not an option. Finally the end result is quite a humongous set of simple values which I want to store in the most effecient way and also store precalculated averages, maximums and minimums of certain combinations.

One solution is creating unique function-objects in JS for every single update, which I believe is not an efficient way?

The main objective is to decrease the time taken to perform an aggregation of this type, bandwidth usage is secondary.

When using MongoDB I'm currently doing a conditional upsert as a part of an aggregation process, on the form (simplified alot):

db.dbname.update({attr1 : value1, attr2 : value2},
                 {"$inc" : { avg : current_value, nr : 1}},
                 false (multi), true (upsert))

But I want to able to keep a maximum (and minimum) value as well, without having to retrieve the document. Something along the lines of:

db.dbname.update({ attr1 : value1, attr2 : value2},
                 {"$inc" : { avg : current_value, nr : 1},
                  "$setIfBigger" : { max : current_value}},
                 false (multi), true (upsert))

Is this possible in an efficient way?

My current, extremely inefficient, solution is that I check for a current aggregation document, and if it exists I update the values accordingly, and if it doesn't I create a new document. Example (again, simplified alot, but the essence is there):

var obj = db.dbname.findOne({attr1 : value1, attr2 : value2},{_id:1});
if (obj != null) {
   db.dbname.update({attr1 : value1, attr2 : value2},
                    {"$inc" : { avg : current_value, nr : 1},
                     "$set" : { max : (obj.max > current_value ? obj.max : current_value}},
                    false (multi), true (upsert));
} else {
   db.dbname.save({attr1 : value1, attr2 : value2, 
                   avg : current_value, nr : 1,
                   max : current_value});
}

The actual program is written in Java and uses the mongo-API, and the aggregation process is quite complex and uses composition techniques way beyond Javascript to communicate with other servers, ergo mapreduce is not an option. Finally the end result is quite a humongous set of simple values which I want to store in the most effecient way and also store precalculated averages, maximums and minimums of certain combinations.

One solution is creating unique function-objects in JS for every single update, which I believe is not an efficient way?

The main objective is to decrease the time taken to perform an aggregation of this type, bandwidth usage is secondary.

Share Improve this question edited Sep 22, 2017 at 17:57 CommunityBot 11 silver badge asked Apr 4, 2011 at 14:39 flindebergflindeberg 5,0071 gold badge26 silver badges37 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 15

This can now be done much more easily in the MongoDB 2.6 release which includes Insert and Update Improvements. Specifically there are new $min and $max operators that perform a conditional update depending on the relative size of the specified value and the current value of a field.

So for example this update:

db.scores.update( { _id: 1 }, { $max: { highScore: 950 } } )

would conditionally update the specified document if 950 is greater than the current value of highScore.

One solution is creating unique function-objects in JS for every single update, which I believe is not an efficient way?

May not work as you'd like it to:

https://jira.mongodb.org/browse/SERVER-458

Is this possible in an efficient way?

The issue you're facing is that you want MongoDB to perform an upsert with some more complex logic. So you want to leverage the document-level locking to effectively "trigger" multiple complex changes all at once.

You're not the first one to want this, unfortunately it's not available right now. There are several server bugs tied to this type of "more complex update behavior". You may want to watch / vote on a few of the following to check for progress.

$set only when inserting, add only when not existing, push and set at the same time, coordinate a "size" with $addToSet.

In particular, SERVER-458 seems closest to what you want.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1738762368a4073645.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信