聚合管道 (Aggregation Pipeline)
聚合管道由一个或多个处理文档的阶段组成:
-
每个阶段对输入文档执行一个操作。例如,某个阶段可以过滤文档、对文档进行分组并计算值。
-
从一个阶段输出的文档将传递到下一阶段。
-
一个聚合管道可以返回针对文档组的结果。例如,返回总值、平均值、最大值和最小值。
使用 db.collection.aggregate() 方法运行的聚合管道不会修改集合中的文档,除非管道包含 $merge 或 $out 阶段。
以下聚合管道示例包含两个阶段,并返回按披萨名称分组后,各款中号披萨的总订单数量:
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
阶段:
-
从披萨订单文档过滤出
size
为medium
的披萨。 -
将剩余文档传递到
$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 }#排序,-1倒序 } ] )
$project
将带所请求字段的文档传递至管道中的下个阶段。指定的字段可以是输入文档中的已有字段或新计算的字段。
{ $project: { <specification(s)> } }
$project
采用的文档可以指定包含字段、抑制 _id
字段、添加新字段以及重置现有字段的值。您也可以指定排除字段。
<field>: <1 or true> |
指定包含字段。非零整数也被视为
true 。 |
_id: <0 or false> |
指定抑制 要有条件地排除字段,请使用 |
<field>: <expression> |
添加新字段或重置现有字段的值。 如果表达式的计算结果为 |
<field>: <0 or false> |
指定排除某个字段。 要有条件地排除字段,请使用 |