doc.save() versus Model.update() - Question/thought

3,727 views
Skip to first unread message

Dan MacTough

unread,
Mar 9, 2012, 10:48:41 AM3/9/12
to mongoo...@googlegroups.com
I haven't thought this through, but I want to put it out there before I forget. My brain is leaky like that.

Please disabuse me of any misconceptions I betray below.

Okay. So, when you get a doc with a query, you can modify the doc's properties, then call doc.save() to save the changes. Mongoose applies all the validators, setters, etc. to the doc. Last I checked, behind the scenes, Mongoose actually uses a mongo update() command to save the changes to the doc, but, it doesn't use atomic operators for things like $inc and $addToSet (my two favorite operators). So, you always run the risk of a race condition.

Now, you can use Model.update, but then you don't get the validators etc.

It's a dilemma.

So, here's the question/thought: Would it be possible and worthwhile to perhaps allow a user to include a mongo update object, e.g., { $inc: { field: 1 }, $addToSet: { array_field: 'val' } } to the doc.save() call -- doc.save(updateObj [optional], callback). Then when you call doc.save(), Mongoose would perform the validations, apply setters, etc. on the updated doc properties (if any), calculate a diff object as usual, and then merge the updateObj with that diff object.

One problem with that approach would be how do then update the doc properties in the calling function. Like I said, I haven't really thought this through, but I thought it might be a worthwhile discussion.

Aaron Heckmann

unread,
Mar 23, 2012, 3:24:29 PM3/23/12
to mongoo...@googlegroups.com
On Fri, Mar 9, 2012 at 10:48 AM, Dan MacTough <danma...@gmail.com> wrote:
Mongoose actually uses a mongo update() command to save the changes to the doc, but, it doesn't use atomic operators for things like $inc and $addToSet (my two favorite operators). So, you always run the risk of a race condition.

Not correct. Both $inc and $addToSet are used when using the applicable methods (number.$inc, array.$addToSet).

var M = mongoose.model('M', new Schema({ num: Number, arr: [] }));
var m = new M({ num: 4, arr: [4,5,6] });
m.num.$inc();
m.arr.$addToSet(5,6,7);
m.save() // -> M.update({ _id: m._id }, { $inc: { num: 1 }, $addToSet: { arr: [7] }})



Would it be possible and worthwhile to perhaps allow a user to include a mongo update object, e.g., { $inc: { field: 1 }, $addToSet: { array_field: 'val' } } to the doc.save() call -- doc.save(updateObj [optional], callback)


Perhaps. Right now the hooks system kind of conflates the save method by hooking into the arguments but we are looking at an alternatives for v3.x.

--
Aaron



Dan MacTough

unread,
Mar 25, 2012, 8:54:03 AM3/25/12
to mongoo...@googlegroups.com
Oh, Aaron, thank you thank you thank you thank you. I had NO idea that we could write saves like that. That solves probably 99% of the the problem I thought I had. Maybe 100% -- need to put it into some real code to see for sure.

Aaron Heckmann

unread,
Aug 21, 2012, 1:56:11 PM8/21/12
to mongoo...@googlegroups.com
In v3 we removed MongooseNumber#$inc support because it lead to too
many weird bugs:
http://mongoosejs.com/docs/migration.html#mongoosenumber

If you are still on 2.x the correct usage is:

user.someNumber.$inc()

On Tue, Aug 21, 2012 at 1:44 AM, renatoargh <renat...@gmail.com> wrote:
> Aaron, I just tried your approach and got the following (from mongoose
> 'debug':true):
>
> Mongoose: users.update({ _id: 5033346c60bc3d9405000001 }) { '$set': {
> someNumber: 3 } } { safe: true }
>
> And the code I used:
>
> module.exports.incrementSomeNumber = function(user, callback){
>
> user.someNumber.$inc;
>
> user.save(function(){ callback(); });
>
> };
>
> Is this the same, I mean, is this an atomic operation - I am afraid its not,
> as I dont see the $inc on my update
>
> Em sexta-feira, 23 de março de 2012 16h24min29s UTC-3, Aaron Heckmann
> escreveu:
> --
> --
> http://mongoosejs.com
> http://github.com/learnboost/mongoose
> You received this message because you are subscribed to the Google
> Groups "Mongoose Node.JS ORM" group.
> To post to this group, send email to mongoo...@googlegroups.com
> To unsubscribe from this group, send email to
> mongoose-orm...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/mongoose-orm?hl=en
>
>
>



--
Aaron
@aaronheckmann
Reply all
Reply to author
Forward
0 new messages