Mongoose设置嵌套数组对象值报错及更新不生效问题咨询
错误原因分析
- 第一种写法报错是因为MongoDB原生的
$占位符仅支持单层数组定位,无法同时匹配两层嵌套数组,因此会触发过多占位符的错误。 - 第二种写法匹配到文档但不执行更新,是两个问题共同导致的:
- arrayFilters的过滤条件语法错误,你需要明确指定占位符对应的数组元素的匹配字段,而非直接把占位符变量和值做相等判断。
- 类型不匹配:请求参数拿到的
dayId是字符串类型,而数据库中存储的_id是ObjectId类型,类型不一致导致过滤条件匹配不到目标元素,更新自然不生效。
正确实现代码
首先确保你已经引入mongoose,用于转换ObjectId类型:
const mongoose = require('mongoose');
完整更新代码如下:
await Student.findOneAndUpdate( { "courses.days._id": mongoose.Types.ObjectId(req.params.dayId) }, { $set: { "courses.$[courseItem].days.$[dayItem].attendance": true } }, { arrayFilters: [ // 匹配到包含目标day记录的course元素 { "courseItem.courseId": req.params.courseId }, // 匹配到days数组中_id符合的目标元素 { "dayItem._id": mongoose.Types.ObjectId(req.params.dayId) } ], new: true } );
额外说明
如果你的业务场景中不需要传入courseId,仅通过dayId就可以定位要更新的记录,可以把course的过滤条件调整为:
arrayFilters: [ { "courseItem.days": { $elemMatch: { _id: mongoose.Types.ObjectId(req.params.dayId) } } }, { "dayItem._id": mongoose.Types.ObjectId(req.params.dayId) } ]
如果你的courseId在数据库中存储的也是ObjectId类型,同样需要对req.params.courseId做类型转换后再传入过滤条件。
内容的提问来源于stack exchange,提问作者AnonyXplorer
相关产品推荐
相关产品推荐

