MongoDB聚合分组调整:按区域与日期统计每日去重作业总数
统计需求与现有问题梳理
- 原有基础查询语句
db.action.aggregate([ { $match: {"$and": [{"eventId":{"$in": ["LAS20"]}},{"id": { "$in": db.logins.distinct("id",{"$and": [{"agentRole": {"$in": ["tv_AFC","DV_HP","DV_TECH"]}},{"loginLogoutTime": {"$gte": ISODate("2021-04-20T00:00:00.000-0500"), "$lt": ISODate("2021-04-27T23:59:00.000-0500")}} ]}) } },"timeStamp": {"$gte": ISODate("2021-04-20T00:00:00.000-0400"),"$lt": ISODate("2021-04-27T23:59:00.000-0400")}}]}, { $group: {_id: {Dates: { $dateToString: { format: "%Y-%m-%d", date: "$timeStamp" }}, User: "$id" , Region:"$Region"}, JOBCOUNT: {$addToSet: "$jobId"}}}, { $project: { "_id" : NumberInt(0), "Region": "$_id.Region" , "Dates" : "$_id.Dates","TotalJOB" : {$size:"$JOBCOUNT"}} } ])
- 原查询输出特征
原查询按「日期+用户+区域」三个维度分组,统计单用户每日的去重作业数,输出示例:
Region Dates TotalJOB nw 2021-04-27 2
- 核心调整目标
- 移除分组逻辑中的用户id维度,不再按用户拆分统计值
- 分组粒度调整为区域Region + 按日截断的时间戳
- 聚合计算各区域每日的去重作业jobId总数
- 目标输出格式参考:
REGION Trunc(Timestamp) count(*) pw 05th-feb-21 1165 nw 05th-feb-21 2165
- 关联文档结构参考
action集合的单条文档结构示例:
{ "_id" : ObjectId("6076719fd1d4bc00124041"), "recordPublishIndicator" : "Y", "eventId" : "LAS20", "eventName" : "", "timeStamp" : ISODate("2021-04-14T04:37:51.085Z"), "eventMethod" : "AI response", "resourceName" : "", "targetType" : "", "resourseUrl" : "", "operationName" : "getLastReleaseNumber", "functionStatus" : "SUCCESS", "results" : "{\"flowStatus\":\"SUCCESS\",\"flowStatusMessage\":\"\",\"lastReleaseNumber\":\"0.1.175\",\"lasUpgradeType\":\"F\"}", "pageId" : "", "ban" : "", "jobId" : "", "wrid" : "", "jobType" : "", "id" : "bt9976", "Region" : "NW", "__v" : 0 }
- 之前调整时的异常输出
调整过程中曾出现结果完全丢失Region维度的问题,输出示例:
{ "Dates" : "2021-04-17", "TotalJOB" : 6485 }, { "Dates" : "2021-04-18", "TotalJOB" : 2618 }
该结果无法体现不同区域的作业量差异,不符合统计要求。
异常原因定位
- 异常来源于调整分组逻辑时,误将
Region字段从$group阶段的分组键中移除。MongoDB聚合时会自动跨区域合并同日期的作业数据,最终投影阶段无法取出Region字段,直接造成统计维度缺失。 - 原分组逻辑的多层维度如果被误删其中的非目标维度,会导致聚合粒度直接降低,丢失细分维度的统计值。
修正后的聚合查询
db.action.aggregate([ // 保留原有过滤逻辑,确保统计范围和之前的口径一致 { $match: { "$and": [ {"eventId": {"$in": ["LAS20"]}}, { "id": { "$in": db.logins.distinct( "id", { "$and": [ {"agentRole": {"$in": ["tv_AFC","DV_HP","DV_TECH"]}}, { "loginLogoutTime": { "$gte": ISODate("2021-04-20T00:00:00.000-0500"), "$lt": ISODate("2021-04-27T23:59:00.000-0500") } } ] } ) } }, { "timeStamp": { "$gte": ISODate("2021-04-20T00:00:00.000-0400"), "$lt": ISODate("2021-04-27T23:59:00.000-0400") } } ] } }, // 调整分组粒度:移除用户id维度,仅保留日期、区域两个统计维度 { $group: { _id: { Dates: { $dateToString: { format: "%Y-%m-%d", date: "$timeStamp", timezone: "-04:00" // 与过滤条件的时区对齐,避免日期截断偏差 } }, Region: "$Region" }, JOBCOUNT: {$addToSet: "$jobId"} // 对jobId做去重收集 } }, // 投影输出符合要求的结构 { $project: { _id: NumberInt(0), Region: "$_id.Region", Dates: "$_id.Dates", TotalJOB: {$size: "$JOBCOUNT"} } } ])
调整说明
- 查询完全保留原有口径的过滤条件,统计范围和之前保持一致,不会出现数据偏差
- 若需要匹配目标示例中的
05th-feb-21日期格式,只需将$dateToString中的format参数调整为%dth-%b-%y即可适配输出样式 - 聚合阶段用
$addToSet收集jobId的方式,可自动实现作业去重,无需额外过滤空jobId的逻辑
内容的提问来源于stack exchange,提问作者bp_db
相关产品推荐
相关产品推荐

