【问题标题】:Virtual field not setting field in mongoose model虚拟字段未在猫鼬模型中设置字段
【发布时间】:2018-03-23 11:08:30
【问题描述】:

我是 nodeJS 和猫鼬的新手。我正在尝试制作一个不将密码保存为纯文本的用户模型。在其他后端框架中,您可以通过使用虚拟字段使用 ORM 来完成此操作。我查阅了 Mongoose 的文档,发现这是可以实现的。在 dics 之后,我创建了以下 Mongoose 模型。请注意,这不是最终实现,只是为了测试我对 Mongoose 如何处理虚拟字段的理解。

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const userSchema = new Schema({
  name: {type: String, required: true},
  email: {type: String, required: true},
  passwordHash: {type: String, required: true}
});

userSchema.virtual("password")
  .get(() => this._password)
  .set(val => {
    this._password = val;
    console.log("setting: ", val);
    this.passwordHash = "test";
  })


module.exports = mongoose.model("Users", userSchema);

我对这个模型也有以下测试

it("should not save passwords as plain test", done => {
    const user = new User({name: "john", email: "john@example.com",     password: "password1234"});
    console.log(user);
    user.validate(({errors}) => {
      expect(errors).to.not.exist
    });
    done();
  }); 

测试失败,因为我有一个错误。该错误表明缺少 passwordHash 字段。我知道我有该字段,但我在 set 函数中将值“test”分配给 this.passwordHash,就像文档说的那样。这就是我卡住的地方。非常感谢任何指导。

【问题讨论】:

    标签: node.js express mongoose-schema


    【解决方案1】:

    我认为问题在于 userSchema.virtual("password") 函数中的 this 上下文

    userSchema.virtual("password")
      .get(() => this._password) // this points to global object
      .set(val => {
        this._password = val; // this points to global object
        console.log("setting: ", val);
        this.passwordHash = "test";
      });
    

    这是您无法使用箭头功能时的例外情况之一。

    userSchema.virtual("password")
      .get(function() {
          return this._password;
      })
      .set(function(val) {
        this._password = val;
        console.log("setting: ", val);
        this.passwordHash = "test";
      });
    

    让我知道它现在是否正常工作。

    我的一般建议:对于哈希/检查密码,请使用 Schema.pre('save') 挂钩。例如:

    // before save user
    userSchema.pre('save', function(next) {
      if (this.isModified('password')) { //only if password is modified then hash
        return bcrypt.hash(this.password, 8, (err, hash) => {
          if (err) {
            return next(err);
          }
          this.password = hash; //save hash in UserSchema.password in database
          next();
        });
      }
      next();
    });
    

    Schema.pre 是 中间件 的一部分。更多关于 mongoose 中的中间件:http://mongoosejs.com/docs/middleware.html

    【讨论】:

    • 阿图尔!你完全正确!使用胖箭头函数时,我完全忘记了“this”的词法范围!我也更喜欢你的替代方法。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-05
    • 2023-03-31
    • 2016-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-10
    相关资源
    最近更新 更多