如何用Node.js+Mongoose实现MongoDB中对象数组的增改逻辑
在Mongoose中实现MongoDB数组元素的“存在则更新,不存在则添加”操作
方案一:分步更新(低并发场景适用)
先尝试更新匹配moduleId的数组元素,若未找到匹配项则执行新增操作:
const courseId = "6392f2611e7d670eca9712fa"; const newModule = { moduleId: 2, moduleTitle: "Module Title 3", moduleDescription: "Module 3 description", totalSessions: 8, }; // 第一步:尝试更新已有moduleId对应的元素 const updatedCourse = await MasterCourse.findOneAndUpdate( { _id: courseId, "courseModules.moduleId": newModule.moduleId }, { $set: { "courseModules.$.moduleTitle": newModule.moduleTitle, "courseModules.$.moduleDescription": newModule.moduleDescription, "courseModules.$.totalSessions": newModule.totalSessions, }, }, { new: true } // 返回更新后的完整文档 ); if (!updatedCourse) { // 未找到匹配元素,执行新增 const addedCourse = await MasterCourse.findOneAndUpdate( { _id: courseId }, { $push: { courseModules: newModule } }, { new: true } ); console.log(addedCourse.courseModules); // 输出更新后的数组 } else { console.log(updatedCourse.courseModules); // 输出更新后的数组 }
方案二:原子性聚合管道更新(推荐,支持高并发)
利用MongoDB 4.2+支持的聚合管道更新,通过一次原子操作完成“更新/新增”逻辑,避免并发冲突:
const courseId = "6392f2611e7d670eca9712fa"; const newModule = { moduleId: 2, moduleTitle: "Module Title 3", moduleDescription: "Module 3 description", totalSessions: 8, }; const finalUpdatedCourse = await MasterCourse.findOneAndUpdate( { _id: courseId }, [ { $set: { courseModules: { $cond: { // 判断当前数组中是否存在目标moduleId if: { $in: [newModule.moduleId, "$courseModules.moduleId"] }, // 存在则遍历数组,更新匹配的元素 then: { $map: { input: "$courseModules", as: "module", in: { $cond: { if: { $eq: ["$$module.moduleId", newModule.moduleId] }, then: newModule, else: "$$module", }, }, }, }, // 不存在则将新元素追加到数组末尾 else: { $concatArrays: ["$courseModules", [newModule]] }, }, }, }, }, ], { new: true } ); console.log(finalUpdatedCourse.courseModules); // 输出更新后的数组
注意事项
- 若你的
courseModules子文档需要自动生成_id,Mongoose会默认添加;若不需要,可在Schema中配置courseModules: [{ type: ModuleSchema, _id: false }]。 - 方案二要求MongoDB版本≥4.2,同时Mongoose版本需支持对应语法(建议使用5.10+版本)。
内容的提问来源于stack exchange,提问作者Ankit Kumar
相关产品推荐
相关产品推荐

