如何从3个不同collection中按name分组计算price(含嵌套存储)的平均值
实现方案
完全可以实现,以下提供两种常用场景的实现方式:
方案1:MongoDB 原生聚合查询实现
如果这三个集合存储在MongoDB中,直接用聚合管道即可完成计算,核心逻辑是:
- 合并三个集合的所有文档
- 统一提取不同层级的price字段并转换为数值类型
- 按name字段分组计算平均值
- 格式化输出为要求的结构
聚合语句示例:
db.a.aggregate([ // 合并另外两个集合的所有文档 { $unionWith: "b" }, { $unionWith: "c" }, // 统一提取price字段,适配不同存储层级 { $addFields: { priceNum: { $toDouble: { $cond: { if: { $gt: ["$data.detail.price", null] }, then: "$data.detail.price", else: "$price" } } } } }, // 按name分组,计算平均价格,取第一条记录的id作为输出id(可按需调整id生成规则) { $group: { _id: "$name", avgPrice: { $avg: "$priceNum" }, id: { $first: "$id" } } }, // 格式化输出结构 { $project: { _id: 0, id: 1, name: "$_id", price: { $toString: { $round: ["$avgPrice", 1] } } } }, // 按id排序为可选步骤 { $sort: { id: 1 } } ])
方案2:原生JavaScript 直接处理数组实现
如果已经把三个集合的数据拉取到代码层为数组格式,可以直接用JS处理:
// 示例数据源 const collectionA = [{"id":1, "price": "1200", "name": "x1"},{"id":2, "price": "2000", "name": "x2"},{"id":3, "price": "3000", "name": "x3"}] const collectionB = [{"id":1, "price": "1500", "name": "x1"},{"id":2, "price": "2500", "name": "x2"},{"id":3, "price": "3125", "name": "x3"}] const collectionC = [{"id":1, "data": {"detail": {"price": 1900}}, "name": "x1"},{"id":2, "data": {"detail": {"price": 2900}}, "name": "x2"},{"id":3, "data": {"detail": {"price": 3500}}, "name": "x3"}] // 合并所有数组 const allItems = [...collectionA, ...collectionB, ...collectionC] const priceMap = new Map() // 按name分组统计总价和对应记录数 allItems.forEach(item => { const price = item.data?.detail?.price ? Number(item.data.detail.price) : Number(item.price) if (priceMap.has(item.name)) { const entry = priceMap.get(item.name) entry.total += price entry.count += 1 } else { priceMap.set(item.name, { id: item.id, total: price, count: 1 }) } }) // 生成符合要求的结果数组 const result = Array.from(priceMap.entries()).map(([name, entry]) => ({ id: entry.id, name, price: (entry.total / entry.count).toFixed(1) })) console.log(result)
你可以根据自己的使用场景选择对应方案。
内容的提问来源于stack exchange,提问作者devmrh
相关产品推荐
相关产品推荐

