如何在PyMongo聚合中调整Project阶段实现按Assignee分组输出
调整PyMongo聚合查询以实现按用户分组的结果结构
现有PyMongo聚合代码可统计每个用户的工单类型数量:
DB.ticket.aggregate([ { "$match": {"project": project_id}, }, { "$group": { "_id": { "assignee": "$assignee.uid", "type": "$type" }, "count": { "$sum": 1} }, }, { "$project": {"assignee": "$_id.assignee", "type": "$_id.type", "count": 1, "_id":0} } ])
当前输出结果:
[ { "assignee": "John", "count": 2, "type": "Open" }, { "assignee": "John", "count": 3, "type": "Completed" }, { "assignee": "Jason", "count": 2, "type": "In Progress" }, { "assignee": "Jason", "count": 2, "type": "Completed" } ]
需要调整聚合管道,将输出转换为以处理人(assignee)为主键的结构,期望输出如下:
{ "John": [ { "count": 2, "type": "Open" }, { "count": 3, "type": "Completed" } ], "Jason": [ { "count": 2, "type": "In Progress" }, { "count": 2, "type": "Completed" } ] }
修改后的聚合管道代码
你需要在现有$group和$project之后,新增两个聚合阶段,先按assignee再次分组合并结果,再将用户ID转为对象键名:
DB.ticket.aggregate([ { "$match": {"project": project_id}, }, { "$group": { "_id": { "assignee": "$assignee.uid", "type": "$type" }, "count": { "$sum": 1} }, }, { "$project": {"assignee": "$_id.assignee", "type": "$_id.type", "count": 1, "_id":0} }, // 按处理人分组,将同用户的类型统计结果封装为数组 { "$group": { "_id": "$assignee", "types": { "$push": { "type": "$type", "count": "$count" } } } }, // 将用户键值对收集后转为目标结构 { "$group": { "_id": null, "data": { "$push": { "k": "$_id", "v": "$types" } } } }, { "$replaceRoot": { "newRoot": { "$arrayToObject": "$data" } } } ])
各阶段作用说明
- 初始
$match:过滤出指定项目下的工单数据。 - 第一次
$group:按处理人和工单类型组合分组,统计每种类型的工单数量。 $project:重塑文档结构,提取并展示需要的字段。- 第二次
$group:按处理人单独分组,将该用户的所有类型统计结果合并到一个数组中。 - 第三次
$group:把所有用户的键值对(键为用户ID,值为类型统计数组)收集到同一个数组里。 $replaceRoot+$arrayToObject:将收集到的键值对数组转换为目标对象结构,最终得到以用户ID为键的输出。
内容的提问来源于stack exchange,提问作者Abhishek
相关产品推荐
相关产品推荐

