MongoDB嵌套数组场景下带upsert的update更新操作实现方法
MongoDB会议指标追加Upsert解决方案
前提要求
- MongoDB版本 ≥ 4.2(支持update操作传入聚合管道)
实现逻辑
通过聚合管道形式的update操作,一次性覆盖「会议不存在新建」「会议存在用户不存在新增用户」「会议用户都存在追加指标到最后一个会话」三类场景,不需要额外事务或多次查询。
具体代码
首先把你要写入的指标数据定义为变量:
// 可替换为你实际要插入的业务数据 const payload = { "conf": "conference12345", "uid": "2dd8b4e3-9dcd-4da6-bc36-aa0988dc9642", "metrics": { "ts": 1234567891, "bw":356 } }
然后执行带upsert的update操作:
db.collection.update( // 匹配条件:按会议ID查询 { "conf": payload.conf }, // 聚合管道,分两步处理嵌套数组 [ // 第一步:不存在对应用户则先新增用户 { $set: { "users": { $cond: { if: { $not: { $in: [payload.uid, "$users.uid"] } }, then: { $concatArrays: [ {$ifNull:["$users", []]}, [ { uid: payload.uid, sessions: [] } ] ] }, else: "$users" } } } }, // 第二步:对目标用户的最后一个会话追加指标 { $set: { "users": { $map: { input: "$users", as: "u", in: { $cond: { if: { $eq: ["$$u.uid", payload.uid] }, then: { uid: "$$u.uid", sessions: { $cond: { // 用户无会话则新建会话存入指标 if: { $eq: [{ $size: "$$u.sessions" }, 0] }, then: [ [ payload.metrics ] ], // 有会话则追加指标到最后一个会话 else: { $concatArrays: [ { $slice: ["$$u.sessions", 0, { $subtract: [ { $size: "$$u.sessions" }, 1 ] } ] }, [ { $concatArrays: [ { $last: "$$u.sessions" }, [ payload.metrics ] ] } ] ] } } } }, else: "$$u" } } } } } } ], // 开启upsert,会议不存在时自动创建文档 { upsert: true } )
效果验证
- 新会议新用户场景:传入
conf: "conferenceXYZ"的测试数据,执行后会自动创建完整的会议文档,结构和你给出的示例完全一致 - 已有用户场景:传入
conf: "conference12345"的测试数据,执行后对应用户的最后一个会话数组末尾会新增传入的指标项
内容的提问来源于stack exchange,提问作者HKHAIT
相关产品推荐
相关产品推荐

