Mongoose findOneAndUpdate返回更新结果但未修改数据库数组对象
解决Mongoose findOneAndUpdate返回更新结果但数据库未修改的问题
可能的原因及对应解决方案
1. 查询条件中的ID类型不匹配
确保查询条件里的donations._id是mongoose.Types.ObjectId类型,而非字符串。Mongoose虽会自动转换字符串ID,但部分场景下(如字符串格式不标准)会导致数组元素匹配失败,更新逻辑未执行,但内存中的文档会被修改并返回。
修改代码:
const mongoose = require('mongoose'); const updated = await DonationModel.findOneAndUpdate( { _id: mongoose.Types.ObjectId('document Object Id'), 'donations._id': mongoose.Types.ObjectId('Object Id of donation Object') }, { 'donations.$.assigned': true }, { new: true } );
2. Mongoose中间件(Hook)拦截了更新
检查是否定义了pre('findOneAndUpdate')钩子,钩子函数可能修改了更新参数、未正确调用next(),或抛出未捕获错误,导致更新操作未提交到数据库。
示例:确保钩子内正确调用next():
DonationSchema.pre('findOneAndUpdate', function(next) { // 业务逻辑执行完成后必须调用next() next(); });
3. 缺少更新验证选项
添加runValidators: true选项,强制Mongoose执行Schema验证。若更新操作违反Schema规则(如字段类型不匹配),Mongoose默认会静默失败,导致数据库未更新但返回内存修改后的文档。
修改代码:
const updated = await DonationModel.findOneAndUpdate( { _id:'document Object Id', 'donations._id': 'Object Id of donation Object' }, { 'donations.$.assigned': true }, { new: true, runValidators: true // 启用更新验证 } );
4. 事务未提交
如果代码运行在Mongoose事务中,需确保事务已提交。未提交的事务会导致内存中能看到修改结果,但数据库不会持久化。
示例:
const session = await mongoose.startSession(); session.startTransaction(); try { const updated = await DonationModel.findOneAndUpdate( { _id:'document Object Id', 'donations._id': 'Object Id of donation Object' }, { 'donations.$.assigned': true }, { new: true, session } ); await session.commitTransaction(); // 必须提交事务 } catch (err) { await session.abortTransaction(); } finally { session.endSession(); }
5. 缓存或文档实例干扰
使用lean: true选项返回纯JSON对象而非Mongoose文档实例,避免内存缓存干扰。同时可直接查询MongoDB数据库确认更新是否执行。
修改代码:
const updated = await DonationModel.findOneAndUpdate( { _id:'document Object Id', 'donations._id': 'Object Id of donation Object' }, { 'donations.$.assigned': true }, { new: true, lean: true // 返回纯JSON结果 } );
6. 检查MongoDB操作日志
查看MongoDB的mongod.log日志(通常位于数据目录下),确认更新命令是否被执行,是否有错误信息,以此定位具体失败原因。
内容的提问来源于stack exchange,提问作者Sachin Yadav
相关产品推荐
相关产品推荐

