MongoDB聚合中按Key合并对象数组并更新Value的问题
MongoDB聚合$merge阶段合并对象数组并求和更新analytics字段
解决方案
修改$merge阶段的whenMatched逻辑,通过数组转键值对、求和合并、再转回数组的方式,实现相同type的value累加,新增type自动添加:
{ $merge: { into: 'analytics', on: ['key'], whenMatched: [ { $replaceWith: { key: '$key', analytics: { $map: { input: { $objectToArray: { $reduce: { input: { $concatArrays: [ { $map: { input: "$$existing.analytics", as: "item", in: { k: "$$item.type", v: "$$item.value" } } }, { $map: { input: "$$new.analytics", as: "item", in: { k: "$$item.type", v: "$$item.value" } } } ] }, initialValue: {}, in: { $setField: { field: "$$this.k", input: "$$value", value: { $sum: [ { $ifNull: [ "$$value.$$this.k", 0 ] }, "$$this.v" ] } } } } } }, as: "entry", in: { type: "$$entry.k", value: "$$entry.v" } } } } } ], whenNotMatched: 'insert' } }
逻辑拆解
- 统一数组元素格式:用
$map将原有文档($$existing)和新文档($$new)的analytics数组元素,转换成{k: type值, v: value值}的结构,再通过$concatArrays合并成一个数组。 - 按type求和合并:用
$reduce遍历合并后的数组,以type为键构建对象,遇到相同键时累加value(用$ifNull处理首次出现的键,避免空值报错)。 - 还原目标数组结构:用
$objectToArray将求和后的对象转回数组,再通过$map把每个元素还原成{type: "...", value: ...}的原始格式。
效果验证
执行后,原有文档与新生成文档合并后会得到期望结果:
{ "key": "product1", "analytics": [ { "type": "CLICK", "value": 7 }, { "type": "SELL", "value": 49.98 }, { "type": "ABANDON", "value": 1 } ] }
内容的提问来源于stack exchange,提问作者Vitaly Radchik
相关产品推荐
相关产品推荐

