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
相关产品推荐
相关产品推荐

