14

I want to start taking advantage of Mongooses document versioning (__v key). I was having an issue actually incrementing the version value, then I found that you have to add this.increment() when executing a query.

Is there a way to have automatically incremented? For now, I just added it to the pre middleware for a update-type queries:

module.exports = Mongoose => {
    const Schema = Mongoose.Schema

    const modelSchema = new Schema( {
        name: Schema.Types.String,
        description: Schema.Types.String
    } )

    // Any middleware that needs to be fired off for any/all update-type queries
    _.forEach( [ 'save', 'update', 'findOneAndUpdate' ], query => {
        // Increment the Mongoose (__v)ersion for any updates
        modelSchema.pre( query, function( next ) {
            this.increment()
            next()
        } )
    } )
}

Which seems to work.. But I kinda thought there would already be a way to do this within Mongoose.. am I wrong?

Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
Justin
  • 1,959
  • 5
  • 22
  • 40

2 Answers2

12

I'd say this is the way to go. pre middleware fits exactly this need, and I don't know any other way. In fact this is what I'm doing in all my schemas.

What you need to be aware of though, is the difference between document and query middleware. Document middleware are executed for init, validate, save and remove operations. There, this refers to the document:

schema.pre('save', function(next) {
  this.increment();
  return next();
});

Query middleware are executed for count, find, findOne, findOneAndRemove, findOneAndUpdate and update operations. There, this refers to the query object. Updating the version field for such operations would look like this:

schema.pre('update', function( next ) {
  this.update({}, { $inc: { __v: 1 } }, next );
});

Source: mongoose documentation.

Justin
  • 1,959
  • 5
  • 22
  • 40
Antoine
  • 5,055
  • 11
  • 54
  • 82
  • So you're saying I would have to split up the `__v` incrementation between the document update methods (`save`) and the query update methods (`findOneAndUpdate`, `update`)? Something like **[this](http://pastebin.com/QGxgLhQz)**? – Justin Feb 10 '16 at 16:24
  • Yes, you have to split the incrementation between document and query middlewares. I suggest having 2 different methods as shown in my post, rather than trying to squeeze 2 different ways in a single method. – Antoine Feb 10 '16 at 16:33
  • FYI @Antoine, the Query MW function needed the `next` callback, which I found out from [this thread](http://stackoverflow.com/questions/35540047/incorrect-document-revision-number-found-in-post-update-middleware). I updated your post – Justin Feb 22 '16 at 15:34
  • 2
    For some reason, if I put `next` beside the query update it increments in a step of 2 –  Mar 27 '20 at 17:33
0

For me the simplest way to do that is :

clientsController.putClient = async (req, res) => {

const id = req.params.id;
const data = req.body;
data.__v++;

await Clients.findOneAndUpdate({ _id: id }, data)
    .then( () => 
    {
        res.json(Ok);
    }
    ).catch ( err => {
        Error.code = '';
        Error.error = err;
        res.json(Error);
    })

};