问题与mongoose .findByIdAndUpdate和更新前挂钩

时间:2018-03-05 15:30:33

标签: node.js mongoose mongoose-schema

我有一个名为UserSchema的mongoose架构,它存储有关所有用户的信息。 我想让用户更改他的信息,我尝试使用.findByIdAndUpdate。 这是相关的代码:

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

});

但是,在尝试更改信息时,我收到以下错误消息:Cannot read property 'password' of undefined。我很确定这是由更新前挂钩引起的,但我无法将其删除,因为我需要它来处理我的“忘记密码”功能。 这是代码:

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

我很困惑为什么它使用了prehook,因为在钩子里它正在寻找findOneandUpdate当我尝试更改数据时我正在使用findByIdAndUpdate

我尝试使用.update(),但这也不起作用。有谁知道我做错了什么以及如何解决它?

3 个答案:

答案 0 :(得分:3)

看起来getUpdate不是你想要的,试试这样:

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

关于第二个问题,findByIdAndUpdate是findOneAndUpdate的包装器。以下代码直接来自 Mongoose的源代码供您参考

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

代码中的注释为:

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

您可以在此处阅读自己的源代码:https://github.com/Automattic/mongoose/blob/9ec32419fb38b74b240280aaba162f9ee4416674/lib/model.js

答案 1 :(得分:0)

假设您打算将整个文档作为更新传递(例如,使用upsert: true-我认为这也是公认的答案),并且想要使用一个功能,则可以:

async function validation(next, self) {
    // validation code here 
}

YourSchema.pre('validate', async function(next) { validation(next, this) });
YourSchema.pre('findOneAndUpdate', async function(next) { validation(next, this._update) });

您只需将this替换为this._update,以通知该函数正在验证什么。

答案 2 :(得分:0)

由于我无法访问 _update 属性,这对我有用:

UserSchema.pre('findOneAndUpdate', async function (this) {
  let update = {...this.getUpdate()};

  // Only run this function if password was modified
  if (update.password){

  // Hash the password
  const salt = genSaltSync();
  update.password = await hash(this.getUpdate().password, salt);
  this.setUpdate(update);
  }
})