Node.js+Mongoose如何更新或新增对象内嵌套数组中的对象元素
实现方案
你可以通过「先尝试更新匹配项,无匹配时新增元素」的逻辑实现需求,代码如下:
第一步:先修正Schema定义(优化类型校验)
把SlotTracker的bookings字段明确指定为Slot类型数组,避免类型异常:
const SlotSchema = new Schema({ aDate: { type: Date }, aShift: { type: String }, slotsAvailable: { type: Number }, slotsBooked: { type: Number } }); const SlotTrackerSchema = new Schema({ courtID: { type: Number }, // 注意数据库中存储的是courtID(大写D),和定义的字段名大小写要对齐,否则会查不到数据 bookings: [SlotSchema] // 明确嵌套数组的结构为Slot }); const SlotTracker = mongoose.model('SlotTracker', SlotTrackerSchema);
第二步:编写更新逻辑
// 假设你传入的参数如下: const targetCourtId = 2; // 请求的场地ID const inputDate = new Date('2021-06-12T00:00:00.197Z'); // 传入的日期参数 const inputShift = 'morning'; // 传入的班次参数 const changeCount = 1; // 本次预订占用的slot数量,可根据实际业务调整 // 第一步:先尝试更新匹配的slot const updateResult = await SlotTracker.updateOne( // 查询条件:匹配对应courtID,且bookings数组中存在aDate、aShift都匹配的元素 { courtID: targetCourtId, 'bookings.aDate': inputDate, 'bookings.aShift': inputShift }, // 更新操作:原子修改匹配到的slot的可预约数和已预约数 { $inc: { 'bookings.$.slotsAvailable': -changeCount, 'bookings.$.slotsBooked': changeCount } } ); // 第二步:如果没有匹配到任何可更新的元素,就往对应场地的bookings数组新增slot if (updateResult.matchedCount === 0) { await SlotTracker.updateOne( { courtID: targetCourtId }, { $push: { bookings: { aDate: inputDate, aShift: inputShift, slotsAvailable: 3, // 新slot的初始可预约数,可根据实际业务调整 slotsBooked: changeCount } } } ); }
注意事项
- 这里用
$inc原子操作符做数值增减,可避免并发请求下的数据不一致问题- 如果你使用MongoDB 4.2以上版本,也可以用单条聚合更新语句实现需求,上述分步骤写法可读性更高,更易维护
内容的提问来源于stack exchange,提问作者Dhanraj Nimbalkar
相关产品推荐
相关产品推荐

