Mongoose.save()未实际修改MongoDB数据问题求助
MongoDB数组内对象更新无报错但未生效问题解决
尝试更新MongoDB数据库中数组内的对象,谷歌搜索未找到有效解决办法,且MongoDB未返回任何错误,因此陷入困境。
操作逻辑:通过ID获取SnagList文档,遍历数组修改对应元素后调用save()方法,该操作无报错,但数据库数据并未实际更新。另外,向数组push新对象时功能正常,查阅Mongoose文档未找到相关问题说明。
原代码:
const { SnagList } = require("../models/schemaModel.js"); //get the details of the snag update from the request object, get the relevant customer from the database, loop through the snags array and update with the new info we just received in the request const snagUpdate = async (req, res) => { const snagId = req.body.update.id; const snagLocation = req.body.update.location; const snagDescription = req.body.update.snagDetails; try { const list = await SnagList.findById(req.body.customerId); list.snags.forEach((snag) => { if (snag.id === snagId) { snag.location = snagLocation; snag.snagDetails = snagDescription; } }); await list.save(); res.send("Snag update processed"); } catch (err) { console.error(err); res.send("Error during update process"); } }; module.exports = snagUpdate;
问题原因
Mongoose的变更追踪机制默认不会检测数组内部嵌套对象的属性修改。当你直接遍历数组修改对象属性时,Mongoose无法识别到这部分变更,执行save()时不会将修改同步到数据库。而push新元素时,数组本身的结构(长度)发生变化,Mongoose能检测到,所以操作生效。
解决方案
方案一:手动标记数组为已修改
在修改完数组元素后,调用markModified()方法告诉Mongoose该字段已变更,再执行save():
修改后的代码:
const { SnagList } = require("../models/schemaModel.js"); const snagUpdate = async (req, res) => { const snagId = req.body.update.id; const snagLocation = req.body.update.location; const snagDescription = req.body.update.snagDetails; try { const list = await SnagList.findById(req.body.customerId); list.snags.forEach((snag) => { if (snag.id === snagId) { snag.location = snagLocation; snag.snagDetails = snagDescription; } }); // 手动标记snags数组已修改 list.markModified('snags'); await list.save(); res.send("Snag update processed"); } catch (err) { console.error(err); res.send("Error during update process"); } }; module.exports = snagUpdate;
方案二:直接用数据库更新操作(更高效)
使用Mongoose的findOneAndUpdate配合MongoDB的$set操作符,直接在数据库层面定位并更新数组内的目标对象,无需先查询再修改,避免变更追踪问题:
const { SnagList } = require("../models/schemaModel.js"); const snagUpdate = async (req, res) => { const snagId = req.body.update.id; const snagLocation = req.body.update.location; const snagDescription = req.body.update.snagDetails; try { const updatedList = await SnagList.findOneAndUpdate( // 查询条件:找到对应customerId,且snags数组中包含id为snagId的对象 { _id: req.body.customerId, "snags.id": snagId }, // 更新操作:用$set修改匹配到的数组元素的对应属性 { $set: { "snags.$.location": snagLocation, "snags.$.snagDetails": snagDescription } }, // 配置项:返回更新后的文档 { new: true } ); if (!updatedList) { return res.send("No matching SnagList or snag found"); } res.send("Snag update processed"); } catch (err) { console.error(err); res.send("Error during update process"); } }; module.exports = snagUpdate;
内容的提问来源于stack exchange,提问作者PIE
相关产品推荐
相关产品推荐

