Mongoose用findOneAndUpdate按ObjectId更新嵌套数组字段不生效问题
问题根因
你当前的更新语句的字段路径指向错误:你写的{phone: 22222}是尝试给Event文档的根层级新增/更新phone字段,而非更新guests嵌套数组中匹配项的phone字段。MongoDB更新嵌套数组中匹配到的元素,需要使用**位置运算符$**来指代查询条件命中的那个数组元素。
修正后的代码
module.exports.checkIn = async(req, res) => { const idNum = req.body.guest; Event.findOneAndUpdate( {"_id": req.params.id, "guests._id": idNum }, // 用$指代匹配到的guests数组元素,指定更新该元素的phone字段 {"guests.$.phone": 22222 }, // 可选:加new: true参数会返回更新后的文档,默认返回更新前的旧文档 { new: true }, (error, data) => { if(error){ res.send(error); } else { res.send(data); } }); }
如果你要和函数的async声明匹配,更推荐用async/await写法避免回调嵌套:
module.exports.checkIn = async(req, res) => { try { const updatedEvent = await Event.findOneAndUpdate( {"_id": req.params.id, "guests._id": req.body.guest }, {"guests.$.phone": 22222 }, { new: true } ) res.send(updatedEvent) } catch (error) { res.send(error) } }
额外注意事项
- 请确认
req.body.guest的类型和guests子文档的_id类型一致,都是ObjectId类型,若传的是字符串格式的ID,需要先用mongoose.Types.ObjectId(idNum)做类型转换,否则会出现匹配不到数组元素的问题。 - 默认情况下
findOneAndUpdate返回的是更新前的旧文档,如果没有加new: true参数,拿到的返回值看不到更新后的结果属于正常现象,实际数据库已更新的话可以直接查库确认。
内容的提问来源于stack exchange,提问作者econobro
相关产品推荐
相关产品推荐

