MongoDB更新JSON对象数组报错:qualifications字段类型不符排查
MongoDB嵌套数组更新报错问题解决
问题背景
数据Schema定义如下:
qualifications:[ { Experience: [{ title: String, companyName: String, location: String, years: Number }], Education:[ { school: String, years: Number, }], Licences: [String], Honnors: [String], }],
需求是向Education数组中添加新对象,尝试了以下添加代码:
const updateEducation = async (req, res) => { try { const user = await User.findOneAndUpdate( { _id: req.body.userid }, { $push: { qualifications:{ Education: { school: req.body.educationSchool, years: req.body.educationYearText } } }, }, { new: true } );
删除代码如下:
const deleteEducation = async (req, res) => { try { const user = await User.findOneAndUpdate( { _id: req.body.userid }, { $pull: { "qualifications.Education": { school: req.body.school } }, } );
但添加时出现错误:
"error": "Plan executor error during findAndModify :: caused by :: The field 'qualifications' must be an array but is of type object in document"
问题原因
报错核心是qualifications是数组类型,但你用$push直接给它赋值一个对象,这会把整个数组覆盖成单个对象,违反了原本的Schema类型定义,所以MongoDB抛出类型错误。
另外不管是添加还是删除操作,都没正确定位到qualifications数组内部元素的Education子数组——因为qualifications本身是数组,里面只有一个对象元素,必须先定位到这个数组元素,才能操作它的Education子数组。
正确解法
1. 向Education数组添加对象
需要用数组索引(比如0,因为你的qualifications数组只有一个元素)或者$定位符来指定要操作的qualifications元素,然后对其下的Education数组执行$push:
const updateEducation = async (req, res) => { try { const user = await User.findOneAndUpdate( { _id: req.body.userid }, { $push: { // 用0索引定位qualifications数组的第一个(也是唯一)元素 "qualifications.0.Education": { school: req.body.educationSchool, years: parseInt(req.body.educationYearText) // 注意转成Number类型,匹配Schema } } }, { new: true } ); res.status(200).json(user); } catch (err) { res.status(500).json({ error: err.message }); } };
如果未来qualifications数组可能有多个元素,且需要匹配特定条件的元素,可以用$定位符(前提是查询条件能匹配到qualifications里的目标元素):
// 假设要匹配qualifications中某个条件的元素,比如有特定Experience的元素 const user = await User.findOneAndUpdate( { _id: req.body.userid, "qualifications.Experience.title": "目标职位" // 匹配qualifications数组中的元素 }, { $push: { "qualifications.$.Education": { // $代表查询条件匹配到的qualifications元素索引 school: req.body.educationSchool, years: parseInt(req.body.educationYearText) } } }, { new: true } );
2. 删除Education数组中的对象
同理,需要定位到qualifications数组元素下的Education数组,执行$pull:
const deleteEducation = async (req, res) => { try { const user = await User.findOneAndUpdate( { _id: req.body.userid }, { $pull: { "qualifications.0.Education": { school: req.body.school } } }, { new: true } // 加上这个选项返回更新后的文档,方便验证 ); res.status(200).json(user); } catch (err) { res.status(500).json({ error: err.message }); } };
内容的提问来源于stack exchange,提问作者facosob
相关产品推荐
相关产品推荐

