首页
mongodb
Linux
云原生
常用bat文件
Maven教程
设计模式
Oracle常用知识梳理
更多……
申请加入课程
MongDB简介
MongDB及其附属工具介绍和安装
MongoDB 备份(mongodump)与恢复(mongorestore)
MongoDB基础DML和DDL操作
MongoDB 可视化工具
MongoDB 索引
MongoDB 聚合
MongDB 复制与分片集群
MongoDB 监控
MongoDB 查询分析
MongoDB 概念解析
MongoDB GridFS
MongoDB Java
Redis、Memcache和MongoDB的区别
MongoDB的其它关键知识点
MongoDB k8s单节点部署和备份
MongoDB 的配置mongodb.conf
MongoDB k8s下部署 Replica Set
MongoDB 状态查询
MongoDB 数据库的日志解析
MongoDb 常见错误处理方法收集
MongoDB 一次性能测试和问题解决
MongoDB 聚合
星辰
2018-10-12
0
0
1220
人
0
人评论
0
人举报
# MongoDB 聚合 > MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果。有点类似sql语句中的 count(*)。 ## aggregate() 方法 aggregate() 方法的基本语法格式如下所示: `> db.COLLECTION_NAME.aggregate(AGGREGATE_OPERATION)` * 常用聚合表达式,辅助说明数据 ``` { _id: ObjectId(7df78ad8902c) title: 'MongoDB Overview', description: 'MongoDB is no sql database', by_user: 'runoob.com', url: 'http://www.runoob.com', tags: ['mongodb', 'database', 'NoSQL'], likes: 100 }, { _id: ObjectId(7df78ad8902d) title: 'NoSQL Overview', description: 'No sql database is very fast', by_user: 'runoob.com', url: 'http://www.runoob.com', tags: ['mongodb', 'database', 'NoSQL'], likes: 10 }, ``` | 表达式 | 描述 | 实例 | | ------------ | ------------ | ------------ | | $sum | 计算总和。 | db.COLLECTION_NAME.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}]) | | $avg | 计算平均值 | db.COLLECTION_NAME.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}]) | | $min | 获取集合中所有文档对应值得最小值。 | db.COLLECTION_NAME.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}]) | | $max | 获取集合中所有文档对应值得最大值。 | db.COLLECTION_NAME.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}]) | | $push | 在结果文档中插入值到一个数组中。 | db.COLLECTION_NAME.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}]) | | $addToSet | 在结果文档中插入值到一个数组中,但不创建副本。 | db.COLLECTION_NAME.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}]) | | $first | 根据资源文档的排序获取第一个文档数据。 | db.COLLECTION_NAME.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}]) | | $last | 根据资源文档的排序获取最后一个文档数据 | db.COLLECTION_NAME.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}]) | ## 下面给出一些mongo的聚合操作和mysql的语句的对应案例 我们先准备如下测试数据 ``` > db.table1.find().pretty() { "_id" : ObjectId("5bc0042226cc694727bd1940"), "cust_id" : "abc123", "ord_date" : ISODate("2018-10-12T10:13:11.102Z"), "status" : "A", "price" : 50, "items" : [ { "sku" : "xxx", "qty" : 25, "price" : 1 }, { "sku" : "yyyy", "qty" : 25, "price" : 1 } ] } { "_id" : ObjectId("5bc0046226cc694727bd1941"), "cust_id" : "abc234", "ord_date" : ISODate("2018-10-12T10:13:11.102Z"), "status" : "A", "price" : 50, "items" : [ { "sku" : "xxx", "qty" : 25, "price" : 1 }, { "sku" : "yyyy", "qty" : 25, "price" : 1 } ] } { "_id" : ObjectId("5bc0047c26cc694727bd1942"), "cust_id" : "abc234", "ord_date" : ISODate("2018-10-12T10:13:11.102Z"), "status" : "B", "price" : 10, "items" : [ { "sku" : "xxx", "qty" : 15, "price" : 2 }, { "sku" : "yyyy", "qty" : 35, "price" : 3 } ] } { "_id" : ObjectId("5bc006ff26cc694727bd1943"), "cust_id" : "abc234", "ord_date" : ISODate("2018-09-12T10:13:11.102Z"), "status" : "B", "price" : 10, "items" : [ { "sku" : "xxx", "qty" : 15, "price" : 2 }, { "sku" : "yyyy", "qty" : 35, "price" : 3 } ] } > ``` * $group,$sum实现分组求和 ``` -- 类似:SELECT cust_id, SUM(price) AS count FROM orders GROUP BY cust_id > db.table1.aggregate([{$group:{_id:"$cust_id",count:{$sum:"$price"}}}]) { "_id" : "abc234", "count" : 60 } { "_id" : "abc123", "count" : 50 } --类似:SELECT COUNT(*) AS count FROM orders > db.table1.aggregate([{$group:{_id:null,count:{$sum:"$price"}}}]) { "_id" : null, "count" : 110 } > -- 对每一个唯一对cust_id和ord_date分组,计算price总和,不包括日期的时间部分 > db.table1.aggregate([{$group:{_id:{cust_id:"$cust_id",ord_date:{month:{$month:"$ord_date"},day:{$dayOfMonth:"$ord_date"},year:{$year:"$ord_date"}}},total:{$sum:"$price"}}}]) { "_id" : { "cust_id" : "abc234", "ord_date" : { "month" : 10, "day" : 12, "year" : 2018 } }, "total" : 60 } { "_id" : { "cust_id" : "abc234", "ord_date" : { "month" : 9, "day" : 12, "year" : 2018 } }, "total" : 10 } { "_id" : { "cust_id" : "abc123", "ord_date" : { "month" : 10, "day" : 12, "year" : 2018 } }, "total" : 50 } > ``` * 筛选 $match 相当于sql中的条件查询 total >=50,其有两种方式一种类似having,另一种类似where ,结果需要和上面查询结果比对查看 对每个唯一的cust_id和ord_date分组,计算价格总和,并只返回price总和大于等于50的记录,且排除日期的时间部分 ``` --GROUP BY cust_id,ord_date HAVING total >= 50 > db.table1.aggregate([{$group:{_id:{cust_id:"$cust_id",ord_date:{month:{$month:"$ord_date"},day:{$dayOfMonth:"$ord_date"},year:{$year:"$ord_date"}}},total:{$sum:"$price"}}},{$match:{total:{$gte:50}}}]) { "_id" : { "cust_id" : "abc234", "ord_date" : { "month" : 10, "day" : 12, "year" : 2018 } }, "total" : 60 } { "_id" : { "cust_id" : "abc123", "ord_date" : { "month" : 10, "day" : 12, "year" : 2018 } }, "total" : 50 } > -- WHERE status = 'A' GROUP BY cust_id,ord_date > db.table1.aggregate([{$match:{status:"A"}},{$group:{_id:{cust_id:"$cust_id",ord_date:{month:{$month:"$ord_date"},day:{$dayOfMonth:"$ord_date"},year:{$year:"$ord_date"}}},total:{$sum:"$price"}}}]) { "_id" : { "cust_id" : "abc234", "ord_date" : { "month" : 10, "day" : 12, "year" : 2018 } }, "total" : 50 } { "_id" : { "cust_id" : "abc123", "ord_date" : { "month" : 10, "day" : 12, "year" : 2018 } }, "total" : 50 } > ``` * $unwind 从输入文档解构数组字段以输出每个元素的文档。简单说就是 可以将数组拆分为单独的文档。 `{ $unwind:
}` ``` { $unwind: { path:
, includeArrayIndex:
, #可选,一个新字段的名称用于存放元素的数组索引。该名称不能以$开头。 preserveNullAndEmptyArrays:
#可选,default :false,若为true,如果路径为空,缺少或为空数组,则$unwind输出文档 } } ``` 如果为输入文档中不存在的字段指定路径,或者该字段为空数组,则$unwind默认会忽略输入文档,并且不会输出该输入文档的文档。 版本3.2中的新功能:要输出数组字段丢失的文档,null或空数组,请使用选项preserveNullAndEmptyArrays。 ``` { "_id" : 1, "item" : "ABC1", sizes: [ "S", "M", "L"] } ``` 以下聚合使用$unwind为sizes数组中的每个元素输出一个文档: ``` > db.table2.find() { "_id" : 1, "item" : "ABC", "sizes" : [ "S", "M", "L" ] } > db.table2.aggregate([{$unwind:"$sizes"}]) { "_id" : 1, "item" : "ABC", "sizes" : "S" } { "_id" : 1, "item" : "ABC", "sizes" : "M" } { "_id" : 1, "item" : "ABC", "sizes" : "L" } > ``` # 管道的概念 管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的参数。 MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。 表达式:处理输入文档并输出。表达式是无状态的,只能用于计算当前聚合管道的文档,不能处理其它的文档。 这里我们介绍一下聚合框架中常用的几个操作: * $project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。 * $match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。 * $limit:用来限制MongoDB聚合管道返回的文档数。 * $skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。 * $unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。 * $group:将集合中的文档分组,可用于统计结果。 * $sort:将输入文档排序后输出。 * $geoNear:输出接近某一地理位置的有序文档。 ## 示例 * 1、$project实例 ``` db.article.aggregate( { $project : { title : 1 , author : 1 , }} ); ``` 这样的话结果中就只还有_id,tilte和author三个字段了,默认情况下_id字段是被包含的,如果要想不包含_id话可以这样: ``` db.article.aggregate( { $project : { _id : 0 , title : 1 , author : 1 }}); ``` * 2.$match实例 ``` db.articles.aggregate( [ { $match : { score : { $gt : 70, $lte : 90 } } }, { $group: { _id: null, count: { $sum: 1 } } } ] ); ``` $match用于获取分数大于70小于或等于90记录,然后将符合条件的记录送到下一阶段$group管道操作符进行处理。 * 3.$skip实例 ``` db.article.aggregate({ $skip : 5 }); ``` 经过$skip管道操作符处理后,前五个文档被"过滤"掉。
所有评论列表
点我发表评论