如何用Mongoose查询指定工匠每月新增商品的数量?
统计指定工匠每月新增商品数量(Mongoose实现)
直接上适配需求的Mongoose聚合查询代码:
const mongoose = require('mongoose'); const Item = require('./models/item'); // 替换为你的Item模型实际路径 // 替换为需要查询的目标工匠ID const targetCraftsmanId = "62f251c28ce1837d3f275908"; async function getMonthlyItemStats() { try { const monthlyStats = await Item.aggregate([ // 1. 筛选指定工匠的所有商品 { $match: { handicraftmen_id: new mongoose.Types.ObjectId(targetCraftsmanId) } }, // 2. 从createdAt中提取年份和月份 { $project: { year: { $year: "$createdAt" }, month: { $month: "$createdAt" } } }, // 3. 按年+月分组,统计当月新增商品数 { $group: { _id: { year: "$year", month: "$month" }, count: { $sum: 1 } } }, // 4. 按时间顺序排序结果 { $sort: { "_id.year": 1, "_id.month": 1 } }, // 可选:将结果格式化为更友好的键值对(如"2022-08": 5) { $project: { _id: 0, monthYear: { $concat: [ { $toString: "$_id.year" }, "-", { $toString: "$_id.month" } ] }, count: 1 } } ]); console.log(monthlyStats); return monthlyStats; } catch (err) { console.error('查询出错:', err); } } // 调用查询函数 getMonthlyItemStats();
代码阶段说明
- $match 阶段:精准过滤目标工匠的商品,必须将字符串ID转为
mongoose.Types.ObjectId,否则无法匹配MongoDB中的ObjectId类型字段。 - $project 阶段:利用MongoDB内置的
$year和$month运算符,从自动生成的createdAt字段中提取时间维度信息。 - $group 阶段:按「年份+月份」组合分组,通过
$sum:1统计每组商品数量,即当月新增商品总数。 - $sort 阶段:按年份和月份升序排列,让结果按时间顺序展示,更易读。
- 可选格式化阶段:通过
$concat拼接年月字符串,同时隐藏默认的_id字段,输出更直观的格式。
进阶:输出中文月份名称
如果需要得到类似{"一月":10, "二月":15}的结果,可修改$project阶段,用$switch将数字月份转为中文名称:
// 替换原有的$project阶段 { $project: { year: { $year: "$createdAt" }, monthName: { $switch: { branches: [ { case: { $eq: [{ $month: "$createdAt" }, 1] }, then: "一月" }, { case: { $eq: [{ $month: "$createdAt" }, 2] }, then: "二月" }, { case: { $eq: [{ $month: "$createdAt" }, 3] }, then: "三月" }, { case: { $eq: [{ $month: "$createdAt" }, 4] }, then: "四月" }, { case: { $eq: [{ $month: "$createdAt" }, 5] }, then: "五月" }, { case: { $eq: [{ $month: "$createdAt" }, 6] }, then: "六月" }, { case: { $eq: [{ $month: "$createdAt" }, 7] }, then: "七月" }, { case: { $eq: [{ $month: "$createdAt" }, 8] }, then: "八月" }, { case: { $eq: [{ $month: "$createdAt" }, 9] }, then: "九月" }, { case: { $eq: [{ $month: "$createdAt" }, 10] }, then: "十月" }, { case: { $eq: [{ $month: "$createdAt" }, 11] }, then: "十一月" }, { case: { $eq: [{ $month: "$createdAt" }, 12] }, then: "十二月" } ], default: "未知月份" } } } }, // 调整$group阶段,按monthName分组 { $group: { _id: "$monthName", count: { $sum: 1 } } }
查询后可通过JS处理将数组转为对象:
const statsObj = monthlyStats.reduce((acc, item) => { acc[item._id] = item.count; return acc; }, {}); console.log(statsObj);
内容的提问来源于stack exchange,提问作者Naveen Chalaka
相关产品推荐
相关产品推荐

