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

MongoDB聚合查询如何返回单个文档而非列表?

解决方法

MongoDB 的聚合查询默认返回数组格式结果,哪怕只匹配到单个文档,所以你需要从返回的数组中提取第一个元素,同时处理当月无订单的空数组情况。

方案一:直接提取数组首元素(推荐)

修改代码,从聚合结果数组中取出第一个元素,若数组为空则返回默认的统计对象(避免返回 undefined):

const getMonthlyRevenue = asyncHandler(async (req, res) => {
  let month = 1 + moment().month();
  console.log(month);

  const monthly = await Order.aggregate([
    {
      $match: {
        $expr: {
          $eq: [{ $month: "$createdAt" }, month],
        },
      },
    },
    {
      $group: {
        _id: { $month: "$createdAt" },
        price: { $sum: "$price" },
      },
    },
  ]);

  // 提取第一个结果,无数据时返回默认值
  const revenueResult = monthly[0] || { _id: month, price: 0 };
  res.status(200).json(revenueResult);
});

方案二:通过聚合管道调整返回格式

如果你想直接通过聚合管道返回单个文档,可以在管道末尾添加 $replaceRoot 和 $arrayToObject 操作,但这种方式相对繁琐,仅当你需要完全通过聚合逻辑处理时使用:

const getMonthlyRevenue = asyncHandler(async (req, res) => {
  let month = 1 + moment().month();
  console.log(month);

  const monthly = await Order.aggregate([
    {
      $match: {
        $expr: {
          $eq: [{ $month: "$createdAt" }, month],
        },
      },
    },
    {
      $group: {
        _id: null,
        month: { $first: month },
        totalPrice: { $sum: "$price" },
      },
    },
    {
      $replaceRoot: {
        newRoot: {
          $arrayToObject: [
            [{ k: "_id", v: "$month" }, { k: "price", v: "$totalPrice" }]
          ]
        }
      }
    },
    {
      $limit: 1
    }
  ]);

  // 同样处理空结果
  const revenueResult = monthly[0] || { _id: month, price: 0 };
  res.status(200).json(revenueResult);
});

说明

  • 方案一逻辑简单直接,适合大多数场景,同时处理了无订单的边界情况,保证返回结构一致。
  • 方案二通过聚合管道重组结果,但最终仍需处理空数组情况,仅在特殊需求下使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 09:12:25