如何修改MongoDB Aggregate查询以实现指定年份下按月分组统计记录数量
修改后的MongoDB聚合查询:指定年份按月统计记录数
这里给你调整好的聚合查询,完美匹配你要的按月统计指定年份记录的需求:
db.records.aggregate([ // 把字符串格式的when字段转为MongoDB Date类型 {"$project": {"_id": 0, "date": {"$dateFromString": {"format": "%Y-%m-%d", "dateString": "$when"}}}}, // 过滤出2021年的所有记录(你可以替换成目标年份) {"$match": {"date": {"$gte": ISODate("2021-01-01"), "$lt": ISODate("2022-01-01")}}}, // 按两位数月份分组统计数量 {"$group": { "_id": {"$dateToString": {"format": "%m", "date": "$date"}}, "count": {"$sum": 1} }}, // 按月份升序排序,保证结果顺序正确 {"$sort": {"_id": 1}} ])
关键修改点说明:
- 新增
$match阶段:用$gte和$lt精准锁定目标年份(比如2021年从1月1日0点到2022年1月1日0点),这种方式比字符串正则匹配更可靠,能避免日期格式不规范导致的漏判。如果你想动态指定年份,也可以用变量生成日期:const targetYear = 2021; db.records.aggregate([ {"$project": {"_id": 0, "date": {"$dateFromString": {"format": "%Y-%m-%d", "dateString": "$when"}}}}, {"$match": { "date": { "$gte": new Date(`${targetYear}-01-01`), "$lt": new Date(`${targetYear + 1}-01-01`) } }}, // 后续阶段同上... ]) - 调整
$group的_id:改用$dateToString把月份格式化为两位数的字符串(比如"01"、"02"),和你给出的预期输出格式完全一致。如果更倾向于数字类型的月份(比如1、2),可以把这部分改成"_id": {"$month": "$date"},数字排序也能保证顺序正确。 - 保留
$sort阶段:确保结果按1月到12月的顺序排列,避免出现乱序的情况。
补充:显示所有12个月(含无记录的月份)
如果希望即使某个月没有记录,也能显示count: 0,可以用下面的扩展查询,通过生成12个月的基准数组再左连接统计结果:
db.records.aggregate([ {"$project": {"_id": 0, "date": {"$dateFromString": {"format": "%Y-%m-%d", "dateString": "$when"}}}}, {"$match": {"date": {"$gte": ISODate("2021-01-01"), "$lt": ISODate("2022-01-01")}}}, {"$group": { "_id": {"$dateToString": {"format": "%m", "date": "$date"}}, "count": {"$sum": 1} }}, {"$sort": {"_id": 1}}, // 生成包含12个两位数月份的基准数组 {"$lookup": { "from": { "$expr": { "$map": { "input": {"$range": [1, 13]}, "as": "month", "in": {"_id": {"$concat": [{"$cond": [{"$lt": ["$$month", 10]}, "0", "" ]}, {"$toString": "$$month"}]}} } } }, "localField": "_id", "foreignField": "_id", "as": "months" }}, {"$unwind": "$months"}, // 无记录的月份count设为0 {"$project": { "_id": "$months._id", "count": {"$ifNull": ["$count", 0]} }} ])
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

