在Express/Node.js中使用Reduce方法统计MongoDB月度FORM条目数量
解决方案
原有代码错误点
- 你错误将查询得到的数组
first_api通过JSON.stringify转为了字符串,reduce是数组专属方法,无法在字符串上调用,这是触发报错的核心原因 - reduce回调函数中返回了未定义的变量
result,应该返回累加器对象r - 未做月份数字到英文名称的转换,无法匹配你需要的输出格式
修改后的api.js路由代码
const express = require('express'); const router = express.Router(); const Api = require('../models/Api'); // 月份英文名称映射,和Date.getMonth()返回的0-11索引一一对应 const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ]; router.get('/', async (req, res) => { try{ // 注意:如果需要统计所有月份的FORM数据,请删除createdDate的时间范围过滤条件 const first_api = await Api.find({ code: 'FORM', // 如需全量统计删除下面两行即可 createdDate: { $gte: new Date(Date.UTC(2021, 4, 16)), $lte: new Date(Date.UTC(2021, 4, 31)) } }, ['createdDate']).sort( { createdDate: -1 }); // 统计逻辑 const countByMonth = first_api.reduce((acc, { createdDate }) => { // 取日期对应的月份英文名称 const monthKey = monthNames[new Date(createdDate).getMonth()]; // 累加计数 acc[monthKey] = (acc[monthKey] || 0) + 1; return acc; }, {}); // 按要求把统计对象放到数组中返回 res.json([countByMonth]); console.log(countByMonth); }catch (err) { res.json({message: err}); } });
代码说明
- 提前定义月份英文映射数组,直接通过
Date.getMonth()返回的索引即可拿到对应的月份英文名称 - 直接对Mongoose返回的文档数组调用reduce做统计,不需要额外做JSON序列化/反序列化处理
- 最终返回的结果用数组包裹,完全匹配你要求的输出格式
- 如果需要统计所有历史数据的月份分布,删除查询条件中的
createdDate时间范围过滤即可
内容的提问来源于stack exchange,提问作者Issac Wu
相关产品推荐
相关产品推荐

