为什么.findByIdAndUpdate绕过猫鼬中间件?

时间:2019-07-02 03:29:09

标签: javascript node.js mongodb mongoose

我已经在这里搜索了这个问题,但是作为一个初学者,答案有些复杂,有些麻烦。我正在使用bcrypt哈希密码,并已设置架构以允许我使用中间件来查看用户是否在哈希之前修改了密码(在初始创建或更新时)。

在发布路由上没有任何问题,但是如果我使用补丁路由,则中间件不会运行。

有人可以帮助我以更简单的方式(即简单的英语)来理解为什么它绕过猫鼬吗?:

const user = await User.findByIdAndUpdate(req.params.id, req.body, { new: true, runValidators: true })

这可行,但是:

const user = await User.findById(req.params.id)

updates.forEach((update) => user[update] = req.body[update])
await user.save()

2 个答案:

答案 0 :(得分:1)

这非常简单:所需的中间件类型(称为query middleware)仅在某些方法上支持/触发。例如from the documentation

  以下模型和查询支持

查询中间件   功能。在查询中间件功能中,这是指查询。

  • 计数
  • deleteMany
  • deleteOne
  • 找到
  • findOne
  • findOneAndDelete
  • findOneAndRemove
  • findOneAndUpdate
  • 删除
  • 更新
  • updateOne
  • updateMany

因此,基本上,您所使用的方法不会触发任何中间件。为此,您必须使用findOneAndUpdateupdateupdateOneupdateMany

在您的第二种情况下它实际起作用。这是由于您实际上正在使用文档中间件。

  

猫鼬有四种类型的中间件:文档中间件,模型   中间件,聚合中间件和查询中间件。文献   以下文档功能支持中间件。在   文档中间件功能,这是指文档。

     

文档中间件受以下支持:

  • 验证
  • 保存
  • 删除
  • init(注意:init挂钩是同步的)

如您所见,save受支持,因此中间件启动。

答案 1 :(得分:0)

应该是这样的:

User.update({username: oldUsername}, {
    username: newUser.username, 
    password: newUser.password
}, function(err, numberAffected, rawResponse) {
   //handle it
});