如何从embedded list中选embedded map元素并实现指定字段求和?
搞定嵌套数组的双重聚合求和问题
嘿,这个需求我太熟了!你想要的是两个聚合结果:一是所有记录total字段的总和,二是所有记录里items数组中id为item1的元素的amount总和。原来的查询写法不符合文档/JSON数据库的语法逻辑,我给你分两种常见场景给出正确实现:
场景1:MongoDB 聚合查询
如果你的数据存在MongoDB里,用聚合管道就能完美实现。这里给你两种写法,按需选择:
写法1:拆分数组后筛选(直观易懂)
db.MyRecord.aggregate([ // 把每个记录的items数组拆成单独文档,方便筛选 { $unwind: "$items" }, // 只保留id是item1的条目 { $match: { "items.id": "item1" } }, // 全局聚合计算两个总和 { $group: { _id: null, totalSum: { $sum: "$total" }, item1AmountSum: { $sum: "$items.amount" } } }, // 重命名字段,匹配你想要的输出格式 { $project: { _id: 0, total: "$totalSum", item1Amount: "$item1AmountSum" } } ])
写法2:不拆分数组(性能更优)
如果数据量较大,不想拆分数组损耗性能,可以直接在聚合阶段用$filter和$map处理:
db.MyRecord.aggregate([ { $group: { _id: null, total: { $sum: "$total" }, item1Amount: { $sum: { // 先筛选当前记录里id为item1的items,再提取amount求和 $sum: { $map: { input: { $filter: { input: "$items", cond: { $eq: ["$$this.id", "item1"] } } }, as: "item", in: "$$item.amount" } } } } } }, // 去掉默认的_id字段 { $project: { _id: 0 } } ])
场景2:支持JSON的关系型数据库(比如PostgreSQL)
如果你的数据存在PostgreSQL这类支持JSON字段的关系型数据库里,可以用JSON函数实现:
SELECT SUM((data->>'total')::INT) AS total, SUM((item->>'amount')::INT) AS item1Amount FROM MyRecord, jsonb_array_elements(data->'items') AS item WHERE item->>'id' = 'item1';
这里jsonb_array_elements会把items数组拆成单独的行,然后筛选出id为item1的条目,最后分别求和即可。
这样两种场景下都能得到你想要的两个聚合结果啦!
内容的提问来源于stack exchange,提问作者AVK
相关产品推荐
相关产品推荐

