简化来讲,设数据集
{“name”: “test”,”count”: {“text”: 1,”face”: 2}}
{“name”: “test”,”count”: {“image”: 3,”face”: 4}}
{“name”: “test”,”count”: {“text”:5,”image”: 6}}
我希望获得的查询结果
{“name”: “test”,”count”: {“text”:6, “face”: 6, “image”: 9}}
是否可以使用mongodb的查询直接做到呢?或者我需要获取所有的记录依次求和?(客户端使用golang,需要考虑驱动适配)
zale 已回答的问题
可以实现,但有点复杂,思路上先将计数器作为数组拆开分别统计,完成后重新分组。
- 利用 $objectToArray,将每个文档 count 子对象拆分为 KV 数组,形式如 { k: “text”, v: 1 }
- 利用 $unwind 将KV 数组拆开为子文档
- 按 name + KV.k 作为分组ID,进行计数,例如 “name=test,KV.k=text” 作为一个单独计数器进行 $sum 统计操作。
- 重新分组,将 name 作为分组ID,统计后的 k/v 作为新的 KV 对象,并置入数组。
- 利用 $arrayToObject,将 KV 对象数组重新合并为 count 子对象。
具体语句如下:
db.test.aggregate( [
//将对象转换为KV数组
{ $addFields: { temp: {$objectToArray: “$count”} } },
//数组拆解
{ $unwind: “$temp”},
//按名称+count计数器进行分组,计算分组总和
{ $group: {
_id: {
name: “$name”,
k: “$temp.k”
},
v: {$sum: “$temp.v”}
} },
//重新分组,将名称作为ID,计算结果置入KV数组
{ $group: {
_id: “$_id.name”,
count: { $push: {k: “$_id.k”, v: “$v”}}
} },
//将KV数组转换回对象
{ $project: {
count: {$arrayToObject: “$count”}
} }
])
zale 已回答的问题