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

Mongoose pre-updateOne文档中间件修改字段未写入数据库求助

Mongoose 5.13.15中updateOne文档中间件设置字段不生效的解决办法

你遇到的问题是:在Mongoose文档级pre('updateOne')中间件中修改updatedBy字段,虽然中间件触发,但数据库里的字段并未更新。这是因为文档级updateOne中间件中直接修改this(文档实例)的字段,不会自动同步到实际执行的数据库更新操作中——document.updateOne()本质是生成一条更新查询语句,而非全量保存文档,内存中文档的修改不会被纳入查询。

解决方案:修改更新查询的内容

在文档级pre('updateOne')中间件中,通过this.getUpdate()获取当前的更新操作对象,将updatedBy字段添加到$set中(如果$set不存在则初始化),再用this.setUpdate()更新查询内容。

修改后的中间件代码如下:

sampleSchema.pre('updateOne', {document: true, query: false}, async function() {
  console.log('updateOne middleware called. This constructor:', this.constructor.name);
  console.log('Setting `updatedBy` to ', currentUserId);
  
  const update = this.getUpdate();
  // 确保$set存在,避免覆盖原有结构
  if (!update.$set) {
    update.$set = {};
  }
  // 将updatedBy加入到更新字段中
  update.$set.updatedBy = currentUserId;
  // 更新查询操作
  this.setUpdate(update);
});

修改后的运行效果

执行原测试代码,输出会变为:

save middleware called. This constructor: model
saved {
  _id: 641cc720863a8421476a16ca,
  color: 'black',
  createdBy: '1',
  updatedBy: '1',
  __v: 0
}
updateOne middleware called. This constructor: model
Setting `updatedBy` to  4
saved 2 {
  _id: 641cc720863a8421476a16ca,
  color: 'green',
  createdBy: '1',
  updatedBy: '4',
  __v: 0
}

此时updatedBy字段会成功更新为4,符合预期。

简化写法

也可以直接使用this.set()方法,它会自动将字段添加到$set操作中,效果一致:

sampleSchema.pre('updateOne', {document: true, query: false}, async function() {
  console.log('updateOne middleware called. This constructor:', this.constructor.name);
  console.log('Setting `updatedBy` to ', currentUserId);
  
  this.set({ updatedBy: currentUserId });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 12:23:18