如何编写MongoDB查询:按年份分组统计指定月份的_id数量
修正后的MongoDB聚合查询实现需求
首先,咱们来梳理下你的需求:要统计1月份的文档数量,并且按年份分组,等价于SQL语句select count(_id), year from table where month="1" group by year。
你的原查询有两个核心问题:
- 直接用
new Date("$displayDate")无法正确解析MongoDB中的字段值,得用MongoDB内置的日期处理操作符来提取月份和年份 - 没有先过滤出1月份的数据,反而把所有月份都做了分组,不符合你要的精准统计需求
情况1:displayDate字段是MongoDB原生Date类型
如果你的displayDate本身就是Date类型,直接用$month和$year操作符即可,正确的聚合查询如下:
db.collection.aggregate([ // 第一步:过滤出1月份的文档 { $match: { $expr: { $eq: [{ $month: "$displayDate" }, 1] } } }, // 第二步:按年份分组,统计每组的文档数量 { $group: { _id: { year: { $year: "$displayDate" } }, count: { $sum: 1 } } }, // 可选:调整输出字段名,让结果更贴近SQL的输出格式 { $project: { _id: 0, year: "$_id.year", count: 1 } } ])
情况2:displayDate字段是字符串类型(比如"2024-01-15")
如果displayDate是字符串格式,需要先把它转换成Date类型,再提取月份和年份:
db.collection.aggregate([ // 先把字符串转成Date类型,再过滤1月份的文档 { $match: { $expr: { $eq: [{ $month: { $toDate: "$displayDate" } }, 1] } } }, // 按年份分组统计数量 { $group: { _id: { year: { $year: { $toDate: "$displayDate" } } }, count: { $sum: 1 } } }, // 可选:调整输出字段名 { $project: { _id: 0, year: "$_id.year", count: 1 } } ])
各阶段作用说明
$match:对应SQL的where month="1",精准过滤出1月份的文档,减少后续分组的数据处理量$group:对应SQL的group by year,按年份分组并统计每组的文档数量($sum:1等价于SQL里的count(_id))- 可选的
$project:把结果中的_id.year重命名为year,移除默认的_id字段,让输出格式更符合你的预期
内容的提问来源于stack exchange,提问作者Intact Abode




