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

12,198

Solution 1

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 
});

Solution 2

try it:

 schema.post('update', function () {
     const modifiedFields = this.getUpdate().$set;
     // ...
 });

Solution 3

There is no direct way of doing it. There is a variable called isNew which is being tracked by mongoose to check if a new document is created.

see Document#isNew for information on Document#isNew

However, you can created your own tracker to check in post save hook to identify wether document is updated or not.

schema.pre('save', function (doc) {
    this.isDocUpdated = false;
    if (this.isModified()) {
        this.isDocUpdated = true;
    }
});

schema.post('save', function (doc) {
    if (this.isDocUpdated) {
        console.log('post save hook called');
    }
});
Share:
12,198

Related videos on Youtube

jemlifathi
Author by

jemlifathi

Updated on June 04, 2022

Comments

  • jemlifathi
    jemlifathi almost 2 years

    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.

  • jemlifathi
    jemlifathi over 6 years
    It returns TypeError: doc.modifiedPaths is not a function There is no function named modifiedPaths in doc
  • Twig2let
    Twig2let over 6 years
    My mistake. It appears modifiedPaths is not available in the post middleware. Have updated the answer.
  • jemlifathi
    jemlifathi over 6 years
    I know there is such function in pre save hook, but as I mentioned in my question I need to check updated fields in pre/post update hook. comprende?
  • Up209d
    Up209d over 4 years
    This is not an answer, whatever fields you throw in $set of update will be listed there, not matter what they are different or same with the old value.
  • omer
    omer over 4 years
    You have a typo in the code. The second hook should be 'post' and not 'pre'
  • joniba
    joniba over 3 years
    very helpful answer!