You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Typegoose中updateOne钩子使用问题:与save钩子差异及类型兼容

在Typegoose中正确配置updateOne的pre文档中间件

你遇到的问题核心其实是Mongoose中间件的默认行为导致的——updateOne的pre钩子默认绑定到Query对象上,而save钩子绑定到文档实例上,两者的this指向完全不同,类型自然不匹配。

根据你提到的Mongoose文档,要把updateOne的中间件改成文档中间件(让this指向文档实例),需要在注册中间件时加上{ document: true, query: false }的配置选项。在Typegoose里,这个配置可以直接通过@pre装饰器的第二个参数传入,具体修改你的代码如下:

@pre<Question>('updateOne', { document: true, query: false }, function () {
  debug.log('updating', this)
  // 现在this的类型就是DocumentType<Question>,和save钩子一致
  this.cname = this.cname || makeCname(this.text)
  this.simple = this.simple || makeCname(this.text)
  recalcVotes(this) // 这里类型就兼容了
  debug.log('cleaned', this)
})

补充说明:

  1. 为什么升级包后不再报错但类型还是不同?
    升级到mongoose@5.11.0和@typegoose/typegoose@7.4.2后,类型定义已经支持了这种配置,但你之前的代码没有传递选项,所以Typegoose仍然推断this是Query类型。只有显式传入{ document: true },Typegoose才会正确把this的类型推断为你的文档类型DocumentType<Question>。

  2. 关于触发场景的区别:

    • 设置{ document: true, query: false }时,中间件只会在调用文档实例的updateOne方法(比如doc.updateOne())时触发;
    • 如果需要让Model.updateOne()也触发中间件,可调整配置为{ query: true },但此时this会回到Query对象,你需要用this.getUpdate()等方法获取更新内容,类型也会不同,根据你的需求选择即可。

内容的提问来源于stack exchange,提问作者dcsan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:33:49