Mongoose中findByIdAndUpdate时好时坏,更新文档报_id未定义错误
问题分析与解决
出现TypeError: Cannot read property '_id' of undefined的核心原因有几个:
1. findByIdAndUpdate默认返回旧文档,且未做存在性校验
Opdrachten.findByIdAndUpdate()默认返回更新前的原始文档,如果遇到以下情况就会触发错误:
- 原始文档的
installateurs数组为空 - 找不到对应
_id的Opdracht文档(此时result为null)
而且你没给外层Promise加错误捕获,导致出现UnhandledPromiseRejectionWarning。
2. 嵌套Promise的错误处理缺失
代码里只有最内层的findByIdAndUpdate加了catch,外层的Opdrachten.findByIdAndUpdate和Installateurs.findById都没有错误捕获,任何一步出错都会导致未处理的Promise拒绝。
3. 更新Installateurs的方式不合理
直接把整个res文档传给findByIdAndUpdate会覆盖文档里的其他字段(比如更新时间、其他关联字段),完全没必要,应该只更新需要修改的字段。
修复后的代码(用async/await简化,完善错误处理)
const Installateurs = require("../../Models/Installateurs.js"); const Opdrachten = require("../../Models/Opdracht.js"); const verzendOpdrachtNaarInstallateur = async (req, response) => { try { // 更新Opdracht,指定{new: true}返回更新后的文档,同时校验文档是否存在 const updatedOpdracht = await Opdrachten.findByIdAndUpdate( req.body._id, req.body, { new: true } ); if (!updatedOpdracht) { return response.status(404).json({ message: "Opdracht不存在" }); } // 校验installateurs数组是否有元素 if (!updatedOpdracht.installateurs || updatedOpdracht.installateurs.length === 0) { return response.status(400).json({ message: "installateurs数组为空,无法获取目标ID" }); } const installateurId = updatedOpdracht.installateurs[0]._id; // 用$push只修改目标字段,避免覆盖其他数据 const updatedInstal = await Installateurs.findByIdAndUpdate( installateurId, { $push: { opdrachten: updatedOpdracht._id, huidigeOpdracht: updatedOpdracht._id } }, { new: true } ); if (!updatedInstal) { return response.status(404).json({ message: "Installateur不存在" }); } response.json(updatedInstal); } catch (err) { console.error("操作出错:", err); response.status(500).json({ message: "服务器内部错误", error: err.message }); } }; module.exports = verzendOpdrachtNaarInstallateur;
额外注意点
- 如果你确实需要使用更新前的Opdracht文档,去掉
{new: true},但必须确保原始文档的installateurs数组有至少一个元素,否则还是会报错。 - 尽量用async/await替代嵌套Promise,代码更易读,错误处理更集中。
- 数据库操作前一定要做存在性校验,避免访问undefined的属性。
内容的提问来源于stack exchange,提问作者Ahmed
相关产品推荐
相关产品推荐

