0

I have a couple places in my application that uses mongoose where I need to handle concurrent modification.

I know there is a version '__v' in all my documents. Most everything I look at points back to this blog:

http://aaronheckmann.tumblr.com/post/48943525537/mongoose-v3-part-1-versioning

Which outlines using the __v field to protect against concurrent array modification within the document. ie:

posts.update({ _id: postId, __v: versionNumber }
           , { $set: { 'comments.3.body': updatedText }})

Do mongoose use the __v field automatically in any way to validate documents when they are saved? Or do you always have to add it to your query statement?

lostintranslation
  • 23,756
  • 50
  • 159
  • 262
  • `mongoose.set("debug",true)` would answer your question for you. Not that I'm a fan of the process in any way. Testing for a specific value of `__v` implies that you already have that infomation present from the document and that there is no way at all you wish to modify content if that value/version is not the same. This is almost never realistic, and in reality your application should not care about this or updates should be applied in a different way where things like "history" are requied. i.e Add to array. If you design proper access patterns then you would have no such problems. – Blakes Seven Feb 19 '16 at 03:24
  • 1
    Quick example from your above code. You should **never** write `comments.3.body` implying udpating the "body" at that index position in the array. Instead you should write `.update({ "_id": postId, "comments._id": commentId },{ "$set": { "comments.$.body": updatedText } })`. In that way you are never updating anything other than the element you know you really want to, and not something else that might now be in the position. The only thing a `__v` would help with is to avoid two users altering the same comment at the same time. But it would be better to only allow changes by the author. – Blakes Seven Feb 19 '16 at 03:34

1 Answers1

0

After reviewing the Mongoose source codes, the __v is really only used for arrays, the VERSION_WHERE is set when updating the array path.

  if ('$push' == op || '$pushAll' == op || '$addToSet' == op) {
    self.$__.version = VERSION_INC;
  }
  // now handling $set, $unset
  else if (/\.\d+\.|\.\d+$/.test(data.path)) {
    // subpath of array
    self.$__.version = VERSION_WHERE;
  }

And per this answer,

var t = Test();
t.name = 'hi'
t.arr = [1, 2, 3, 4, 5, 6];

 t.save(function (err, result) {
    console.log(result);
    // use Mongoose pull method on the array
    t.arr.pull(3);
    t.save(function(err2, result2) {
        console.log(result2)
    });
});

Results:

 { __v: 0,
  name: 'hi',
  _id: 53f59d2a6522edb12114b98c,
  arr: [ 1, 2, 3, 4, 5, 6 ] }
{ __v: 1,
  name: 'hi',
  _id: 53f59d2a6522edb12114b98c,
  arr: [ 1, 2, 4, 5, 6 ] }
Community
  • 1
  • 1
zangw
  • 43,869
  • 19
  • 177
  • 214