“文档” 菜单
文档首页
/
MongoDB Manual
/

聚合管道 (Aggregation Pipeline)

在此页面上

  • 完整的 Aggregation Pipeline 示例
  • 其他聚合管道阶段详细信息
  • 聚合管道表达式
  • 运行聚合管道
  • 使用聚合管道更新文档
  • 其他注意事项
  • 了解详情

聚合管道由一个或多个处理文档的阶段组成:

  • 每个阶段对输入文档执行一个操作。例如,某个阶段可以过滤文档、对文档进行分组并计算值。

  • 从一个阶段输出的文档将传递到下一阶段。

  • 一个聚合管道可以返回针对文档组的结果。例如,返回总值、平均值、最大值和最小值。

如使用通过聚合管道更新中显示的阶段,则可以通过聚合管道更新文档。

注意

您可以 在用户界面运行聚合管道,用于 MongoDB Atlas 中托管的部署。

当您在 MongoDB Atlas 用户界面中的 MongoDB Atlas 部署上运行聚合管道时,您可以预览每个阶段的结果。

本部分展示了使用以下披萨 orders 集合的聚合管道示例:

db.orders.insertMany( [
{ _id: 0, name: "Pepperoni", size: "small", price: 19,
quantity: 10, date: ISODate( "2021-03-13T08:14:30Z" ) },
{ _id: 1, name: "Pepperoni", size: "medium", price: 20,
quantity: 20, date : ISODate( "2021-03-13T09:13:24Z" ) },
{ _id: 2, name: "Pepperoni", size: "large", price: 21,
quantity: 30, date : ISODate( "2021-03-17T09:22:12Z" ) },
{ _id: 3, name: "Cheese", size: "small", price: 12,
quantity: 15, date : ISODate( "2021-03-13T11:21:39.736Z" ) },
{ _id: 4, name: "Cheese", size: "medium", price: 13,
quantity:50, date : ISODate( "2022-01-12T21:23:13.331Z" ) },
{ _id: 5, name: "Cheese", size: "large", price: 14,
quantity: 10, date : ISODate( "2022-01-12T05:08:13Z" ) },
{ _id: 6, name: "Vegan", size: "small", price: 17,
quantity: 10, date : ISODate( "2021-01-13T05:08:13Z" ) },
{ _id: 7, name: "Vegan", size: "medium", price: 18,
quantity: 10, date : ISODate( "2021-01-13T05:10:13Z" ) }
] )

以下聚合管道示例包含两个阶段,并返回按披萨名称分组后,各款中号披萨的总订单数量:

db.orders.aggregate( [
// Stage 1: Filter pizza order documents by pizza size
{
$match: { size: "medium" }
},
// Stage 2: Group remaining documents by pizza name and calculate total quantity
{
$group: { _id: "$name", totalQuantity: { $sum: "$quantity" } }
}
] )

$match 阶段:

  • 从披萨订单文档过滤出sizemedium的披萨。

  • 将剩余文档传递到$group阶段。

$group 阶段:

  • 按披萨name对剩余文档进行分组。

  • 使用$sum计算每种披萨name的总订单quantity。总数存储在聚合管道返回的totalQuantity字段中。

示例输出:

[
{ _id: 'Cheese', totalQuantity: 50 },
{ _id: 'Vegan', totalQuantity: 10 },
{ _id: 'Pepperoni', totalQuantity: 20 }
]

以下示例计算了两个日期之间的披萨订单总额和平均订单数量:

db.orders.aggregate( [
// Stage 1: Filter pizza order documents by date range
{
$match:
{
"date": { $gte: new ISODate( "2020-01-30" ), $lt: new ISODate( "2022-01-30" ) }
}
},
// Stage 2: Group remaining documents by date and calculate results
{
$group:
{
_id: { $dateToString: { format: "%Y-%m-%d", date: "$date" } },
totalOrderValue: { $sum: { $multiply: [ "$price", "$quantity" ] } },
averageOrderQuantity: { $avg: "$quantity" }
}
},
// Stage 3: Sort documents by totalOrderValue in descending order
{
$sort: { totalOrderValue: -1 }
}
] )

$match 阶段:

  • 使用 $gte$lt 将披萨订单文档筛选为指定日期范围内的文档。

  • 将剩余文档传递到$group阶段。

$group 阶段:

  • 使用 $dateToString 按日期对文档进行分组。

  • 对于每个群组,计算:

  • 将分组的文档传递到 $sort 阶段。

$sort 阶段:

  • 按每组的总订单值以降序对文档进行排序 ( -1 )。

  • 返回排序文档。

示例输出:

[
{ _id: '2022-01-12', totalOrderValue: 790, averageOrderQuantity: 30 },
{ _id: '2021-03-13', totalOrderValue: 770, averageOrderQuantity: 15 },
{ _id: '2021-03-17', totalOrderValue: 630, averageOrderQuantity: 30 },
{ _id: '2021-01-13', totalOrderValue: 350, averageOrderQuantity: 10 }
]

提示

另请参阅:

聚合管道由一个或多个处理文档的阶段组成:

  • 阶段不必为每个输入文档输出一个文档。例如,某些阶段可能会产生新文档或过滤掉现有文档。

  • 同一个阶段可以在管道中多次出现,但以下阶段例外:$out$merge$geoNear

  • 要在阶段中计算平均值和执行其他计算,请使用指定聚合操作符聚合表达式。在下一节中,您将了解有关聚合表达式的更多信息。

有关所有聚合阶段,请参阅聚合阶段

某些聚合管道阶段接受聚合表达式,这些表达式:

您可以使用 $accumulator$function 聚合操作符在 JavaScript 中定义自定义聚合表达式。

有关所有聚合表达式,请参阅表达式操作符

聚合表达式使用字段路径访问输入文档中的字段。要指定字段路径,请在字段名称或虚线字段名称(如果该字段位于嵌入式文档中)前添加美元符号 $。例如,用 "$user" 指定 user 字段的字段路径,或用 "$user.name" 指定 "user.name" 字段的字段路径。

"$<field>" 等效于 "$$CURRENT.<field>",其中 CURRENT 为系统变量,而它默认为当前对象的根(除非在特定阶段另行说明)。

要运行聚合管道,请使用:

要使用聚合管道更新文档,请使用:

命令
mongosh 方法
findAndModify

聚合分析管道对值类型和结果大小有限制。请参阅聚合管道限制

聚合管道支持针对分片集合的操作。请参阅聚合管道和分片集合

从 MongoDB 5.0 开始, map-reduce已弃用:

  • 不应使用 map-reduce,而应使用聚合管道。聚合管道提供比 map-reduce 更好的性能和可用性。

  • 您可以使用聚合管道阶段(例如 $group$merge 等)重写 map-reduce 操作。

  • 对于需要自定义功能的 map-reduce 操作,可以使用 $accumulator$function 聚合操作符。可以使用这些操作符在 JavaScript 中定义自定义聚合表达式。

有关 map-reduce 的聚合管道替代方案的示例,请参阅:

要了解有关聚合管道的详细信息,请参阅:

← 聚合操作