How to check modified fields in pre/post update hook in Mongoose.js

jemlifathi picture jemlifathi · Oct 5, 2017 · Viewed 7.8k times · Source

I need to know modified fields or if a specific field was modified in pre or post update hook in a Mongoose schema. I tried the following, but still unable to figure it out:

schema.post('update', function (doc) {
    //check modified fields or if the name field was modified and then update doc
});

I know maybe there is a method isModified like in pre save but I don't know how to do the same with update hooks. Any suggestions will be appreciated.

Answer

Piotr Kowalski picture Piotr Kowalski · Jan 19, 2018

If you want to know what fields you are modifying, then you need to issue an update command by calling save:

Tank.findById(id, function (err, tank) {
  if (err) return handleError(err);

  tank.set({ size: 'large' });
  tank.save(function (err, updatedTank) {
    if (err) return handleError(err);
    res.send(updatedTank);
  });
});

This way pre-save hook will be invoked and you will be having access to:

Document.prototype.modifiedPaths()

because this in pre-save hook refers to the document:

TankSchema.pre('save', function (next) {
  // ...
  this.modifiedPaths();
  // ...
});

On the other hand, you will not be able to achieve the same result when issuing an update command by calling update:

Tank.update({ _id: id }, { $set: { size: 'large' }}, callback);

because when calling update, document hooks (e.g. pre-save, post-save) are not being executed at all. Instead, query hooks are being executed (e.g. pre-update, post-update) in that case. And the issue with query hooks is that this inside of them does not reference the document, so this.modifiedPaths === undefined

schema.post('update', function (doc) {
  // `this` refers to model.Query
  // `doc` refers to CommandResult 
});