You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB订单统计问题:按日期汇总金额+按商品统计数量

MongoDB订单统计问题解决方案

一、按日期汇总订单总金额(覆盖指定区间所有日期,无订单日期补0)

问题原因

原查询统计全为0的核心问题有两个:

  1. 日期匹配逻辑错误:用$dateFromParts生成的订单日期是当天0点UTC时间,但dateRange中的日期是带原始时分秒的时间(如2022-09-30T17:08:56.161Z),两者无法匹配,导致$cond判断始终为false。
  2. 字段映射错误:原代码将订单数和总金额的统计字段搞反,不符合预期结果的字段定义。

修正后的聚合查询

let endDate = new Date("2022-10-04T00:08:17.731Z");
let startDate = new Date("2022-09-25T00:08:56.161");

// 计算日期区间的总天数
const daysDiff = Math.ceil((endDate - startDate) / (1000 * 60 * 60 * 24));

const orderStats = await Order.aggregate([
  // 1. 生成指定区间内的完整日期列表(保持和原dateRange一致的时分秒)
  {
    $documents: Array.from({ length: daysDiff }, (_, index) => {
      const currentDate = new Date(startDate);
      currentDate.setDate(startDate.getDate() + index);
      // 保留原始时间的时分秒,确保日期格式统一
      return {
        date: new Date(
          currentDate.setHours(
            startDate.getHours(),
            startDate.getMinutes(),
            startDate.getSeconds(),
            startDate.getMilliseconds()
          )
        )
      };
    })
  },
  // 2. 关联订单集合,统计对应日期的订单数据
  {
    $lookup: {
      from: "orders", // 替换为你的订单集合实际名称
      let: { targetDate: "$date" },
      pipeline: [
        {
          $match: {
            $expr: {
              $and: [
                { $gte: ["$createdAt", startDate] },
                { $lte: ["$createdAt", endDate] },
                // 用$dateTrunc忽略时分秒,匹配同一天的订单
                {
                  $eq: [
                    { $dateTrunc: { date: "$createdAt", unit: "day" } },
                    { $dateTrunc: { date: "$$targetDate", unit: "day" } }
                  ]
                }
              ]
            }
          }
        },
        {
          $group: {
            _id: null,
            totalAmount: { $sum: "$total" }, // 统计当日订单总金额
            orderCount: { $sum: 1 } // 统计当日订单数量
          }
        }
      ],
      as: "dailyData"
    }
  },
  // 3. 展开关联结果,无数据时保留空值
  { $unwind: { path: "$dailyData", preserveNullAndEmptyArrays: true } },
  // 4. 格式化输出,补全无订单日期的0值
  {
    $project: {
      _id: 0,
      date: "$date",
      totalPrice: { $ifNull: ["$dailyData.totalAmount", 0] },
      subtotal: { $ifNull: ["$dailyData.orderCount", 0] }
    }
  },
  // 5. 按日期升序排序
  { $sort: { date: 1 } }
]);

说明

  • 先通过$documents生成完整日期列表,确保覆盖指定区间的每一天。
  • 用$dateTrunc统一忽略时分秒,精准匹配同一天的订单。
  • 借助$lookup和preserveNullAndEmptyArrays实现左连接,自动为无订单日期补0。

二、按商品统计购买数量

聚合查询实现

const productPurchaseStats = await Order.aggregate([
  // 可选:过滤有效订单(如排除已取消的订单)
  { $match: { status: { $nin: ["Cancelled"] } } },
  // 展开购物车中的商品数组,将每个商品转为单独文档
  { $unwind: "$cart.products" },
  // 按商品ID分组,统计总购买数量
  {
    $group: {
      _id: "$cart.products.product._id",
      totalQuantity: { $sum: "$cart.products.quantity" }
    }
  },
  // 格式化输出字段
  {
    $project: {
      _id: 0,
      productId: "$_id",
      totalQuantity: 1
    }
  },
  // 可选:按购买数量降序排序
  { $sort: { totalQuantity: -1 } }
]);

说明

  • $unwind将每个订单中的商品数组拆分为独立文档,确保每个商品能单独统计。
  • $group按商品ID聚合,累加每个商品的购买数量,得到总销量。

内容的提问来源于stack exchange,提问作者James

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 17:25:49