Mongoose通过ObjectId更新嵌套guests数组报错push不是函数如何解决
错误原因
- 异步方法未加
await:Event.findOne是异步查询方法,未加await时guest变量拿到的是Promise实例而非查询结果,Promise没有push方法,触发类型错误。 - Schema定义不规范:当前
guests数组直接将type设为Schema.Types.ObjectId,只能存储ObjectId值,无法附加attended字段,需要调整为嵌套子文档结构。 - 查询与更新逻辑错误:查询条件
'guests.ObjectId'是不存在的字段,且即使查询到Event文档,也需要先定位到guests数组中匹配的子元素再修改属性,不能直接对Event实例调用push。
修正方案
1. 修正Schema定义
const eventSchema = new Schema({ address: String, description: String, guests: [ { _id: Schema.Types.ObjectId, // 存储嘉宾对应的ObjectId attended: String // 存储签到状态 } ], });
2. 修正处理函数
方案A:查询后修改(适合需要做额外逻辑校验的场景)
module.exports.checkIn = async(req, res) => { try { // 查询包含对应嘉宾的活动文档 const event = await Event.findOne({ 'guests._id': req.body.guest }); if (!event) return res.status(404).json({ msg: '活动或嘉宾不存在' }); // 定位匹配的嘉宾条目 const targetGuest = event.guests.find(item => item._id.toString() === req.body.guest); targetGuest.attended = req.body.status; await event.save(); res.status(200).json({ msg: '状态更新成功' }); } catch (err) { res.status(500).json({ msg: '服务器错误', error: err.message }); } }
方案B:原子更新(性能更高,无需查询文档)
利用Mongoose的$定位符直接在数据库层面更新匹配的数组元素:
module.exports.checkIn = async(req, res) => { try { await Event.updateOne( { 'guests._id': req.body.guest }, { $set: { 'guests.$.attended': req.body.status } } ); res.status(200).json({ msg: '状态更新成功' }); } catch (err) { res.status(500).json({ msg: '服务器错误', error: err.message }); } }
内容的提问来源于stack exchange,提问作者econobro
相关产品推荐
相关产品推荐

