MongoDB中子文档字段求和的聚合查询实现
MongoDB多文档按货币类型求和聚合方案
方案一:使用$unwind(高效直观)
这是最常用的实现方式,通过拆解price数组元素,按货币类型分组求和后重组结果:
db.products.aggregate([ // 拆解每个文档的price数组,每个数组元素成为独立文档 { $unwind: "$price" }, // 按currency分组,累加对应amount { $group: { _id: "$price.currency", totalAmount: { $sum: "$price.amount" } } }, // 将分组结果重组为{grossIncome: [...]}结构 { $group: { _id: null, grossIncome: { $push: { amount: "$totalAmount", currency: "$_id" } } } }, // 移除_id字段,只保留目标结果 { $project: { _id: 0 } } ])
方案二:不使用$unwind(适用于特殊场景)
如果需要避免使用$unwind,可以通过合并所有price数组后,利用$reduce和数组转换操作实现分组求和:
db.products.aggregate([ // 收集所有文档的price数组,合并为一个扁平化数组 { $group: { _id: null, allPrices: { $push: "$price" } } }, { $project: { allPrices: { $concatArrays: "$allPrices" }, _id: 0 } }, // 按货币类型分组求和,转换为键值对对象 { $project: { grossIncome: { $arrayToObject: { $reduce: { input: "$allPrices", initialValue: [], in: { $let: { vars: { current: "$$this", existingIndex: { $indexOfArray: ["$$value.currency", "$$this.currency"] } }, in: { $cond: { if: { $ne: ["$$existingIndex", -1] }, then: { $map: { input: "$$value", as: "item", in: { $cond: { if: { $eq: ["$$item.currency", "$$current.currency"] }, then: { currency: "$$item.currency", amount: { $add: ["$$item.amount", "$$current.amount"] } }, else: "$$item" } } } }, else: { $concatArrays: ["$$value", ["$$current"]] } } } } } } } } } }, // 将键值对对象转换为期望的数组格式 { $project: { grossIncome: { $objectToArray: "$grossIncome" } } }, { $project: { grossIncome: { $map: { input: "$grossIncome", as: "item", in: { currency: "$$item.k", amount: "$$item.v.amount" } } } } } ])
结果验证
两种方案执行后都会返回符合需求的结果:
{ "grossIncome": [ { "amount": 430, "currency": "USD" }, { "amount": 70, "currency": "EUR" } ] }
内容的提问来源于stack exchange,提问作者Sam Cherkasov
相关产品推荐
相关产品推荐

