MongoDB聚合查询:如何添加按动作分组统计的actions_total字段
MongoDB聚合查询:如何添加按动作分组统计的actions_total字段
你好呀!看了你现有的聚合管道和目标结果,其实只需要在现有步骤里加一个$addFields阶段,就能生成你需要的actions_total统计数组了,我来给你详细讲讲怎么改。
具体修改方案
在你当前计算total_score的$addFields阶段之后,新增一个$addFields阶段,用来对actions数组按动作分组统计数量和总分:
{ $addFields: { "actions_total": { $map: { input: { $objectToArray: { $reduce: { input: "$actions", initialValue: {}, in: { $mergeObjects: [ "$$value", { "$$this.action": { count: { $add: [ { $ifNull: [ "$$value.$$this.action.count", 0 ] }, 1 ] }, total_score: { $add: [ { $ifNull: [ "$$value.$$this.action.total_score", 0 ] }, "$$this.score" ] } } } ] } } } }, as: "stat", in: { action: "$$stat.k", count: "$$stat.v.count", total_score: "$$stat.v.total_score" } } } } }
步骤拆解说明
- 用
$reduce遍历统计:先遍历actions数组里的每一项,把相同动作的统计数据合并成一个键值对对象——键是动作名称,值是包含count(次数)和total_score(动作总分)的统计对象。 - 用
$objectToArray转换结构:把上面得到的键值对对象转成数组,方便后续调整成你想要的格式。 - 用
$map调整输出格式:把数组里的每一项映射成{action, count, total_score}的结构,和你目标里的格式完全匹配。
完整聚合管道
把这个新增阶段插入到你的现有管道中,最终完整的聚合管道如下:
[ { $match: { timestamp: { $gte: ISODate('2022-11-17T00:00:00'), $lte: ISODate('2022-11-20T23:59:59') } } }, { $lookup: { from: 'actions_score', localField: 'action', foreignField: 'action', as: 'score' } }, { $unwind: { path: "$score" } }, { $project: { 'username': true, 'action': true, 'score': '$score.score', 'timestamp': true, 'role_id': true, '_id': false } }, { $group: { _id: '$username', 'username': { $first: '$username' }, 'role_id': { $first: '$role_id' }, 'actions': { $addToSet: '$$ROOT' } } }, { $addFields: { 'total_score': { "$sum": "$actions.score" } } }, // 新增的统计阶段 { $addFields: { "actions_total": { $map: { input: { $objectToArray: { $reduce: { input: "$actions", initialValue: {}, in: { $mergeObjects: [ "$$value", { "$$this.action": { count: { $add: [ { $ifNull: [ "$$value.$$this.action.count", 0 ] }, 1 ] }, total_score: { $add: [ { $ifNull: [ "$$value.$$this.action.total_score", 0 ] }, "$$this.score" ] } } } ] } } } }, as: "stat", in: { action: "$$stat.k", count: "$$stat.v.count", total_score: "$$stat.v.total_score" } } } } }, { $project: { _id: false, 'actions.username': false, 'actions.role_id': false } } ]
运行这个管道之后,就能得到包含actions_total字段的完整结果,完全符合你的预期需求~
备注:内容来源于stack exchange,提问作者MrOldSir
相关产品推荐
相关产品推荐

