MongoDB aggregate按用户分方向统计通话数据结果异常排查
错误原因
原聚合写法的核心问题是分组粒度设置错误:
- 仅使用
userId作为单级分组的键,$addToSet会直接遍历当前分组下的每一条原始通话记录生成对象存入数组,无法实现按通话方向的二次聚合。 - 写在
$addToSet内部的$sum累加器不会按direction维度生效:MongoDB的聚合累加器仅对当前$group阶段指定的分组键维度生效,嵌套在数组操作符内部的累加器不会触发跨同方向记录的统计逻辑,只会取单条记录的对应值,最终就会出现同方向记录重复、数值未累加的问题。 - 由于每条通话记录的duration值不同,
$addToSet也无法识别同direction的重复项做去重。
修正方法
需要通过两级分组实现需求:
- 第一级分组使用
userId + direction作为联合分组键,先统计出每个用户下每个通话方向的总通话时长、总通话次数 - 第二级分组仅使用
userId作为分组键,将同用户下不同方向的统计结果通过$push整理为目标数组结构
修正后的完整聚合语句:
db.test.aggregate([ // 筛选指定公司的通话记录,逻辑与原写法一致 { $match: { company: "companyName" } }, // 第一级分组:按用户+通话方向双维度聚合 { $group: { _id: { userId: "$userId", direction: "$direction" }, duration: { $sum: "$duration" }, amount: { $sum: 1 } } }, // 第二级分组:按用户维度合并结果,生成目标数组 { $group: { _id: "$_id.userId", data: { $push: { direction: "$_id.direction", duration: "$duration", amount: "$amount" } } } } ])
若需要对最终输出的
data数组按指定规则排序,MongoDB 5.2及以上版本可在最后追加$set阶段,使用$sortArray对数组内元素排序;低版本可在两级分组之间增加$sort阶段预先按direction排序,再执行$push即可保证数组顺序。
内容的提问来源于stack exchange,提问作者dave13e1
相关产品推荐
相关产品推荐

