如何在MongoDB中统计最近X天的记录数?并使用Chart.js展示最近7天每日维修数据(无数据日默认显示0)
解决MongoDB维修数据统计+Chart.js可视化方案
我来帮你搞定这两个需求,先从最近7天每日工单统计(适配Chart.js)说起,再讲最近X天总记录数统计~
一、获取最近7天每日维修工单数量(无记录显示0)
要得到Chart.js需要的[30,40,0,80,75,0,90]这种格式,需要两步:用MongoDB聚合查询统计有数据的日期,再补全缺失日期的0值(数据库层面处理更高效,也可以在前端补全)。
1. MongoDB聚合查询代码
假设你的维修工单集合是Repairs,日期字段是repairDate(必须是Date类型,不是字符串!如果是字符串,需要先通过$toDate转换)。下面的聚合管道会直接返回包含7天数据的数组:
// 计算7天前的起始日期(包含今天,共7天) const sevenDaysAgo = new Date(); sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 6); sevenDaysAgo.setHours(0, 0, 0, 0); // 重置到当天零点,避免时间部分干扰 const pipeline = [ // 第一步:筛选最近7天的维修记录 { $match: { repairDate: { $gte: sevenDaysAgo } } }, // 第二步:按日期分组,统计每日工单数量 { $group: { _id: { $dateToString: { format: "%Y-%m-%d", date: "$repairDate" } }, count: { $sum: 1 } } }, // 第三步:生成最近7天的所有日期数组 { $addFields: { allDates: Array.from({ length: 7 }, (_, i) => { const date = new Date(sevenDaysAgo); date.setDate(date.getDate() + i); return date.toISOString().split('T')[0]; // 转成YYYY-MM-DD格式 }) } }, // 第四步:展开日期数组,准备匹配 { $unwind: "$allDates" }, // 第五步:左连接,填充无数据日期的count为0 { $group: { _id: "$allDates", count: { $first: { $ifNull: ["$count", 0] } } } }, // 第六步:按日期排序,保证顺序正确 { $sort: { _id: 1 } }, // 第七步:提取count数组,输出Chart.js需要的格式 { $group: { _id: null, data: { $push: "$count" } } }, { $project: { _id: 0, data: 1 } } ]; // 执行聚合查询 const result = await db.collection('Repairs').aggregate(pipeline).next(); const chartData = result.data; // 这里就是你要的[30,40,0,...]格式
2. Chart.js可视化代码
拿到chartData后,直接用Chart.js生成图表,下面是柱状图的示例(换成折线图只需要修改type为'line'):
<!-- 先引入Chart.js --> <canvas id="repairDailyChart"></canvas> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script> // 生成日期标签(比如"10/23", "10/24"...) const dateLabels = Array.from({ length:7 }, (_,i) => { const date = new Date(); date.setDate(date.getDate() - 6 + i); return date.toLocaleDateString('zh-CN', { month: '2-digit', day: '2-digit' }); }); // 初始化图表 const ctx = document.getElementById('repairDailyChart').getContext('2d'); new Chart(ctx, { type: 'bar', data: { labels: dateLabels, datasets: [{ label: '每日维修工单数量', data: chartData, // 替换成上面获取的chartData backgroundColor: 'rgba(75, 192, 192, 0.2)', borderColor: 'rgba(75, 192, 192, 1)', borderWidth: 1 }] }, options: { scales: { y: { beginAtZero: true, // Y轴从0开始,避免数据失真 ticks: { stepSize: 10 // 刻度间隔,根据你的数据调整 } } } } }); </script>
二、统计最近X天的记录总数
这个需求很简单,用countDocuments结合日期筛选即可:
/** * 统计最近X天的维修工单总数 * @param {number} x - 天数(比如7代表最近7天,包含今天) * @returns {Promise<number>} 总记录数 */ async function getRecentXDaysTotal(x) { const xDaysAgo = new Date(); xDaysAgo.setDate(xDaysAgo.getDate() - x + 1); // 包含今天的计算方式 xDaysAgo.setHours(0, 0, 0, 0); // 重置到当天零点 return await db.collection('Repairs').countDocuments({ repairDate: { $gte: xDaysAgo } }); } // 调用示例:统计最近7天总数 const total7Days = await getRecentXDaysTotal(7); console.log(`最近7天总维修工单:${total7Days}单`);
注意事项
- 确保
repairDate字段是MongoDB的Date类型,如果是字符串格式,需要在查询时用$toDate转换,比如$match里写成repairDate: { $gte: { $toDate: sevenDaysAgo.toISOString() } } - 如果你的业务里“最近7天”是指过去7天(不含今天),只需要把
sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 6)改成sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7)即可
内容的提问来源于stack exchange,提问作者Ali Parlatti




