如何使用Express和Mongoose向MongoDB中的嵌套数组添加对象
问题核心原因与解决方法
1. 修正Schema定义,匹配现有集合结构
你当前定义的EventSchema是把单个事件作为独立文档存储的,所以直接调用Event.create只会新建独立的事件文档,无法把数据塞到对应日期的events数组中。你需要按照你的集合结构重新定义Schema:
const mongoose = require("mongoose"); // 单个日程事件的子Schema const EventItemSchema = new mongoose.Schema({ event: { type: String, trim: true, required: true, }, start: { type: String, trim: true, }, end: { type: String, trim: true, }, people: { type: String, trim: true, required: true, }, location: { type: String, trim: true, }, description: { type: String, trim: true, }, }); // 单日文档的Schema,对应你events集合里的每个文档 const DaySchema = new mongoose.Schema({ // 对应月中第几天,和你请求参数里的chosenDay对应 dayNumber: { type: Number, required: true, unique: true }, // 存储当日所有事件的数组 events: [EventItemSchema] }); // 第三个参数明确指定映射到你现有的events集合 module.exports = mongoose.model("Day", DaySchema, "events");
注意:你现有的events集合中31个日期文档需要先补上
dayNumber字段,值和前端传的chosenDay匹配(比如从0到30或者1到31),否则查询时会找不到对应文档。
2. 修改添加事件的接口逻辑
你之前写的Event[req.body.chosenDay].events.create是错误用法,Mongoose模型不支持通过下标直接取对应日期的文档,需要用MongoDB的$push更新操作符,找到对应日期的文档后往events数组追加内容:
// 导入修改后的Day模型 const Day = require("../models/Day"); exports.addEvent = async (req, res, next) => { try { const { event, start, end, people, location, description, chosenDay } = req.body; // 构造要添加的事件对象 const newEvent = { event, start, end, people, location, description }; // 找到对应日期的文档,往events数组追加新事件,new: true表示返回更新后的文档 const updatedDay = await Day.findOneAndUpdate( { dayNumber: chosenDay }, { $push: { events: newEvent } }, { new: true, runValidators: true } ); // 处理找不到对应日期的情况 if (!updatedDay) { return res.status(404).json({ success: false, error: "指定的日期不存在" }); } return res.status(201).json({ success: true, // 返回刚添加的事件数据 data: updatedDay.events.slice(-1)[0], }); } catch (err) { // 开发环境可打印err排查具体错误 return res.status(500).json({ success: false, error: "Server has failed", }); } };
扩展:删除事件的实现逻辑
如果要删除指定日期的指定事件,使用$pull操作符即可,示例:
await Day.findOneAndUpdate( { dayNumber: chosenDay }, // 根据事件的_id删除对应条目 { $pull: { events: { _id: 要删除的事件ID } } } );
内容的提问来源于stack exchange,提问作者Tamir Polyakov
相关产品推荐
相关产品推荐

