在猫鼬中进行预更新时,user.isModified 不是函数

Posted

技术标签:

【中文标题】在猫鼬中进行预更新时,user.isModified 不是函数【英文标题】:user.isModified is not a function when doing a pre update in mongoose 【发布时间】:2017-03-02 20:50:49 【问题描述】:

我正在尝试在我正在构建的应用程序中对密码进行哈希处理,当我通过调用此函数 (coffeesctipt) 创建用户时,它们的哈希处理效果很好:

UserSchema.pre 'save', (next) ->
  user = this
  hashPass(user, next)

hashPass = (user, next) ->
  # only hash the password if it has been modified (or is new)
  if !user.isModified('password')
    return next()
  # generate a salt
  bcrypt.genSalt SALT_WORK_FACTOR, (err, salt) ->
    if err
      return next(err)
    # hash the password using our new salt
    bcrypt.hash user.password, salt, (err, hash) ->
      if err
        return next(err)
      # override the cleartext password with the hashed one
      user.password = hash
      next()
      return
    return

但是当我进行更新并拥有此预置时:

UserSchema.pre 'findOneAndUpdate', (next) ->
  user = this
  hashPass(user, next)

我得到TypeError: user.isModified is not a function 如果我在 pres 控制台登录用户保存 pre 记录我正在更新的用户,findandupdate pre 没有,id 有办法访问 pres 中的文档还是我需要这样做另一种方式?

【问题讨论】:

我遇到了同样的问题,但我的问题是在尝试 User.Create 和 new User() 然后 user.save() 我认为你的问题是.pre('update') 钩子中的this 指的是Query 对象而不是模型本身:mongoosejs.com/docs/middleware.html#notes 【参考方案1】:

不要在回调中使用箭头操作符,这会改变 this 的范围。定义一个常规函数;它可能会帮助您解决这个问题。

【讨论】:

您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。【参考方案2】:

在 mongoose 中使用中间件时要小心,在“save”或“updateOne”的情况下,this 指的是查询,而不是文档。它应该是这样的

schema.pre(type,  document: true, query: false , async function (next) 

     if(this.isModified('password')) 
            //Do the hash
     
     next();
);

【讨论】:

【参考方案3】:

我知道这对您来说可能为时已晚,但对于任何未来遇到此问题的编码人员,我认为此解决方案应该可行。 因此,由于 save() 是 .pre 中的中间件,它覆盖了一些 mongoose 的方法,例如 findByIDAndUpdate。如果您在某处触发了补丁请求,您可能想要做的不是使用它,而是像这样分解您的代码:

const user = await User.findById(req.params.id);
    updates.forEach((update) => 
      user[update] = req.body[update];
    );

【讨论】:

【参考方案4】:

您收到错误消息,因为箭头函数更改了“this”的范围。 只需使用

UserSchema.pre('save', function(next))

【讨论】:

问题出在CoffeeScript中,CoffeeScript将箭头函数编译成UserSchema.pre('save', function(next))而不是js箭头函数【参考方案5】:

我在 typescript 上遇到了类似的问题,事实证明这与您也在使用的箭头运算符有关。不知道现在如何在 coffescript 中更改它,但我认为这应该可以解决您的问题。

你必须改变这一行:

hashPass = (user, next) ->

看看这个:https://github.com/Automattic/mongoose/issues/4537

【讨论】:

-> 只是你在咖啡脚本中编写函数的方式,它编译成一个普通函数而不是 => 您的问题与我的问题完全相同。我在答案中链接的 github 问题向您解释了原因。看看吧。 我确实检查过,咖啡中的UserSchema.pre 'findOneAndUpdate', (next) -> 编译为UserSchema.pre('findOneAndUpdate', function(next) ,因此我几乎无法更改我的代码以使其基于该解决方案工作。我的问题是因为 Model.pre 'findOneAndUpdate' 返回的 this 与 Model.pre 'save' 不同。 pre 'save' 将用户返回为 'this' 而 pre on findOneAndUpdate 不会。 我明白了,我正在做一些更多的研究,根据这个讨论似乎不可能完成你想要做的事情:github.com/Automattic/mongoose/issues/964。在线程上有一些您可以使用的建议

以上是关于在猫鼬中进行预更新时,user.isModified 不是函数的主要内容,如果未能解决你的问题,请参考以下文章

使用数组过滤器更新多个嵌套数组在猫鼬中不起作用

如何在猫鼬中保存子文档的数组?

如何在猫鼬中更新嵌套数组值

如何在猫鼬中进行原始 mongodb 操作?

如何在猫鼬中进行原始 mongodb 操作?

在猫鼬中格式化日期