如何用MongoDB的createdAt字段统计指定年月的用户数量?
问题:统计指定月份/年份创建的用户数量时countDocuments返回0
我在搭建管理后台仪表盘,想要统计指定月份或年份创建的用户数量。使用countDocuments()方法查询createdAt字段时,返回结果为0,但预期结果应为2。我的代码如下:
const currentMonth = new Date().getMonth(); const currentYear = new Date().getFullYear(); const newClientThisMonth = await User.countDocuments({ createdAt: { $eq: currentYear }, });
其中newClientThisYear变量返回0而非预期的2。但查询role等其他字段时一切正常,例如:
const clientUsersCount = await User.countDocuments({ role: "user" });
请问正确的实现方式是什么?
正确实现方式
你出错的核心原因是:createdAt是Date类型字段,直接用数字年份去$eq匹配,MongoDB无法识别——它不会自动从日期里提取年份进行比对,自然查不到数据。
下面提供两种可靠的实现方式,优先推荐第一种(性能更优):
方式1:日期范围查询(推荐)
通过构造目标时间段的起始和结束日期,用$gte(大于等于)和$lt(小于)来匹配createdAt的范围,这种方式可以利用createdAt字段上的索引,查询效率更高。
统计指定年份的用户数量
const currentYear = new Date().getFullYear(); // 当年1月1日00:00:00 const startOfYear = new Date(currentYear, 0, 1); // 下一年1月1日00:00:00(作为范围的结束边界) const endOfYear = new Date(currentYear + 1, 0, 1); const newClientThisYear = await User.countDocuments({ createdAt: { $gte: startOfYear, $lt: endOfYear } });
统计指定月份的用户数量
const currentYear = new Date().getFullYear(); const currentMonth = new Date().getMonth(); // 当月第一天00:00:00 const startOfMonth = new Date(currentYear, currentMonth, 1); // 下月第一天00:00:00(作为范围的结束边界) const endOfMonth = new Date(currentYear, currentMonth + 1, 1); const newClientThisMonth = await User.countDocuments({ createdAt: { $gte: startOfMonth, $lt: endOfMonth } });
方式2:使用MongoDB日期操作符(聚合查询)
通过$year、$month等日期操作符提取createdAt中的年份/月份,再进行比对。这种方式更灵活,但无法利用索引,数据量大时性能不如范围查询。
统计指定年份的用户数量
const currentYear = new Date().getFullYear(); const newClientThisYear = await User.countDocuments([ { $match: { $expr: { $eq: [{ $year: "$createdAt" }, currentYear] } } } ]);
统计指定月份的用户数量
注意:MongoDB的$month返回值是1-12,而JS的getMonth()返回0-11,所以需要加1转换:
const currentYear = new Date().getFullYear(); const currentMonth = new Date().getMonth(); const newClientThisMonth = await User.countDocuments([ { $match: { $expr: { $and: [ { $eq: [{ $year: "$createdAt" }, currentYear] }, { $eq: [{ $month: "$createdAt" }, currentMonth + 1] } ] } } } ]);
内容的提问来源于stack exchange,提问作者fathi93
相关产品推荐
相关产品推荐

