在猫鼬中的钩子:这是什么'这个'

时间:2017-06-13 07:08:41

标签: mongoose

我是Express和Mongoose的新手。我正在读这个tutorial 这是教程中的一个片段,其中user正在db中保存。

// Execute before each user.save() call
UserSchema.pre('save', function(callback) {
  var user = this;

  // Break out if the password hasn't changed
  if (!user.isModified('password')) return callback();

  // Password changed so we need to hash it
  bcrypt.genSalt(5, function(err, salt) {
    if (err) return callback(err);

    bcrypt.hash(user.password, salt, null, function(err, hash) {
      if (err) return callback(err);
      user.password = hash;
      callback();
    });
  });
});
  1. 究竟是什么thisthis表示新/已修改的文档,或this表示存储在数据库中的旧文档?我想this是新文件。那么有没有关键字来访问旧文档?在最坏的情况下,我认为,由于这是预先保存,我可以使用findOne访问旧的/已保存的文档。有没有比这种方法更好的东西?
  2. 此处作者正在检查密码是否已更改。所以我想isModified,比较新文档和旧文档中的给定字段,并根据修改返回bool。问题是,虽然保存作者已经保存了哈希,但在检查修改时,我想他应该首先创建哈希,然后检查哈希值是否相同。我是对的,还是我在这里遗漏了一些东西。

1 个答案:

答案 0 :(得分:1)

1 - 在将文档保存到数据库之前调用pre挂钩 - 因此单词“pre”。 this是指保存之前的文档。它将包括您对其字段所做的任何更改。

例如,如果你做了

user.password = 'newpassword';
user.save();

然后,在数据库中插入/更新文档之前,将立即触发挂钩

UserSchema.pre('save', function (next) {
    console.log(this.password); // newpassword
    next(); // do the actual inserting/updating
});

2 - 编辑用户时,可以将表单的密码输入设置为空白。空白密码输入通常意味着不进行任何更改。如果输入新值,则视为更改密码。

然后,您将改变您的架构,如下所示:

为您的密码字段添加setter

let UserSchema = new mongoose.Schema({
    password: {
        type: String,
        // set the new password if it provided, otherwise use old password
        set: function (password) {
            return password || this.password;
        }
    }
    // etc
});

UserSchema.pre('save', function (next) {
    var user = this;
    // hash password if it present and has changed
    if (user.password && user.isModified('password')) {
        // update password
    } else {
        return next();
    }
});

使用这种方法,您可能必须使用例如

var user = new User({ password: req.body.password });
user.save();

user.set({ password: req.body.password });
user.save();

不确定第一个示例是否适用于setter。