MongoDB系列深入理解MongoDB聚合Aggregation
关注公众号【Ccww笔记】,领取干货资料 MongoDB中聚合(aggregate) 操作将来自多个document的value组合在一起,并通过对分组数据进行各种操作处理,并返回计算后的数据结果,主要用于处理数据(诸如统计平均值,求和等)。MongoDB提供三种方式去执行聚合操作:聚合管道(aggregation pipeline)、Map-Reduce函数以及单一的聚合命令(count、distinct、group)。 1. 聚合管道(aggregation pipeline)1.1聚合管道 聚合管道是由aggregation framework将文档进入一个由多个阶段(stage)组成的管道,可以对每个阶段的管道进行分组、过滤等功能,然后经过一系列的处理,输出相应的聚合结果。如图所示: 聚合管道操作: db.orders.aggregate([ { $match: { status: "A" } }, { $group: { _id: "$cust_id", total: { $sum: "$amount" } } }])$match阶段:通过status字段过滤出符合条件的Document(即是Status等于“A”的Document); $group 阶段:按cust_id字段对Document进行分组,以计算每个唯一cust_id的金额总和。1.2 管道 管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的参数,MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。 最基本的管道功能提供过滤器filter,其操作类似于查询和文档转换,可以修改输出文档的形式。 其他管道操作提供了按特定字段或字段对文档进行分组和排序的工具,以及用于聚合数组内容(包括文档数组)的工具。 此外,管道阶段可以使用运算符执行任务,例如计算平均值或连接字符串。总结如下: 管道操作符 常用管道解析$group将collection中的document分组,可用于统计结果$match过滤数据,只输出符合结果的文档$project修改输入文档的结构(例如重命名,增加、删除字段,创建结算结果等)$sort将结果进行排序后输出$limit限制管道输出的结果个数$skip跳过制定数量的结果,并且返回剩下的结果$unwind将数组类型的字段进行拆分表达式操作符 常用表达式含义$sum计算总和,{$sum: 1}表示返回总和×1的值(即总和的数量),使用{$sum: '$制定字段'}也能直接获取制定字段的值的总和$avg求平均值$min求min值$max求max值$push将结果文档中插入值到一个数组中$first根据文档的排序获取第一个文档数据$last同理,获取最后一个数据为了便于理解,将常见的mongo的聚合操作和MySql的查询做类比: MongoDB聚合操作MySql操作/函数$matchwhere$groupgroup by$matchhaving$projectselect$sortorder by$limitlimit $sumsum()$lookupjoin1.3 Aggregation Pipeline 优化聚合管道可以确定它是否仅需要文档中的字段的子集来获得结果。 如果是这样,管道将只使用那些必需的字段,减少通过管道的数据量管道序列优化化管道序列优化化: 1).使用$projector/$addFields+$match 序列优化:当Aggregation Pipeline中有多个$projectior/$addFields阶段和$match 阶段时,会先执行有依赖的$projector/$addFields阶段,然后会新创建的$match阶段执行,如下, { $addFields: { maxTime: { $max: "$times" }, minTime: { $min: "$times" } } }, { $project: { _id: 1, name: 1, times: 1, maxTime: 1, minTime: 1, avgTime: { $avg: ["$maxTime", "$minTime"] } } }, { $match: { name: "Joe Schmoe", maxTime: { $lt: 20 }, minTime: { $gt: 5 }, avgTime: { $gt: 7 } } }优化执行: ...