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
相关产品推荐
相关产品推荐

