如何使用MongoDB聚合嵌套数组统计指定商品的月度销售额?
问题原因及修复方案
1. 直接导致查询不生效的错误:$elemMatch匹配规则写法错误
你当前的$elemMatch: { product: { _id: productId } }写法是要求数组项的product字段完全等于{_id: productId}这个对象,必须完全匹配所有字段才会命中,而不是仅匹配product下的_id字段,因此永远查不到符合条件的订单。
正确的嵌套字段匹配写法应该使用点语法:
products: { $elemMatch: { "product._id": productId } }
2. 隐藏逻辑问题:现有统计逻辑不符合单商品销售额统计要求
就算修正了匹配规则,你当前的聚合逻辑统计的是「包含指定商品的订单总金额」,如果订单同时包含其他商品,统计结果会包含其他商品的销售额,不是指定商品本身的月度销售额。
如果需要统计指定商品的准确销售额,需要调整聚合流程:先展开商品数组、单独匹配目标商品项、再按商品的单价*购买数量累加统计。
修正后的完整代码
public async getIncome(productId?: string) { const date = new Date(); const lastMonth = new Date(date.setMonth(date.getMonth() - 1)); const income = await this.order.aggregate([ { $match: { createdAt: { $gte: lastMonth }, // 先过滤包含目标商品的订单,减少后续计算量 ...(productId && { products: { $elemMatch: { "product._id": productId } }, }), }, }, // 展开商品数组,把每个商品拆为单独文档 { $unwind: "$products" }, // 单独匹配目标商品项 ...(productId ? [{ $match: { "products.product._id": productId } }] : []), { $project: { month: { $month: '$createdAt' }, // 计算单条商品的销售额:单价 * 购买数量 singleSale: { $multiply: ["$products.product.price", "$products.quantity"] } }, }, { $group: { _id: '$month', total: { $sum: '$singleSale' }, }, }, ]); return income; }
补充注意项
- 确认传入的
productId类型和Schema中product._id的类型一致,两者都为String类型,不要传入ObjectId实例,否则类型不匹配也会查询失败。 - 你代码中声明的
previousMonth变量未被使用,如果要统计上上个月到当前的销售额,替换$match中时间判断的边界值即可。
内容的提问来源于stack exchange,提问作者Kai021195
相关产品推荐
相关产品推荐

