Search code examples
node.jsmongoosemongoose-schema

Issue with mongoose .findByIdAndUpdate and pre-update hook


I have mongoose-schema called UserSchema, which stores information about all users. I want to enable the user to change his information, which I try by using .findByIdAndUpdate. This is the relevant code:

router.post("/updateprofile", function(req,res,next) {
    const {id, org, tel, email, firstName, lastName} = req.body;
    Users.findByIdAndUpdate(id, {org : org, tel : tel, email : email, firstName : firstName , lastName : lastName}, function (err, response) {
        if (err) throw err
        res.json(response);
    });

});

However, when trying to change the info, I get the following error-message: Cannot read property 'password' of undefined. I'm pretty sure this is caused by a pre-update hook, but I can not remove it because I need it for my "forgot-password"-functionality. Here's the code:

UserSchema.pre('findOneAndUpdate', function (next) {
    this.update({},{ $set: { password: 
    bcrypt.hashSync(this.getUpdate().$set.password, 10)}} )
    next();
});

I'm confused by why it used that prehook anyway, since in the hook it's looking for findOneandUpdate and when I try to change the data I'm using findByIdAndUpdate.

I tried using .update() instead but that doesn't work either. Does anyone know what I'm doing wrong and how to fix it?


Solution

  • Looks like getUpdate isn't what you want, try it like this:

        UserSchema.pre('findOneAndUpdate', function (next) {
        this._update.password = bcrypt.hashSync(this._update.password, 10)
        next();
    });
    

    With regards to your second question, findByIdAndUpdate is a wrapper around findOneAndUpdate. Here's the code straight from Mongoose's source code for your reference

    Model.findByIdAndUpdate = function(id, update, options, callback) {
      if (callback) {
        callback = this.$wrapCallback(callback);
      }
      if (arguments.length === 1) {
        if (typeof id === 'function') {
          var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\n\n'
              + '  ' + this.modelName + '.findByIdAndUpdate(id, callback)\n'
              + '  ' + this.modelName + '.findByIdAndUpdate(id)\n'
              + '  ' + this.modelName + '.findByIdAndUpdate()\n';
          throw new TypeError(msg);
        }
        return this.findOneAndUpdate({_id: id}, undefined);
      }
    

    The comments in the code read:

    /**
     * Issues a mongodb findAndModify update command by a document's _id field.
     * `findByIdAndUpdate(id, ...)` is equivalent to `findOneAndUpdate({ _id: id }, ...)`.
     *
    

    You can read the source code for yourself here: https://github.com/Automattic/mongoose/blob/9ec32419fb38b74b240280aaba162f9ee4416674/lib/model.js