文档章节

MongoDB聚合(Aggregation Pipeline基础篇上)(三)

LUIS1983
 LUIS1983
发布于 2017/04/26 15:56
字数 1659
阅读 8
收藏 0

一、Aggregate简介 

 

                db.collection.aggregate()是基于数据处理的聚合管道,每个文档通过一个由多个阶段(stage)组成的管道,可以对每个阶段的管道进行分组、过滤等功能,然后经过一系列的处理,输出相应的结果。

               

       图来自https://docs.mongodb.com/manual/aggregation/ 官方网

        我们通过这张图,可以清晰的了解Aggregate处理的过程

  

         1、db.collection.aggregate()可以多个管道,能方便的进行数据的处理。

         2、db.collection.aggregate()使用了MongoDB内置的原生操作,聚合效率非常高,支持类似于SQL Group By操作的功能,而不再需要用户编写自定义的JavaScript例程。

         3、 每个阶段管道限制为100MB的内存。如果一个节点管道超过这个极限,MongoDB将产生一个错误。为了能够在处理大型数据集,可以设置allowDiskUse为true来在聚合管道节点把数据写入临时文件。这样就可以解决100MB的内存的限制。

         4、db.collection.aggregate()可以作用在分片集合,但结果不能输在分片集合,MapReduce可以 作用在分片集合,结果也可以输在分片集合。

    5、db.collection.aggregate()方法可以返回一个指针(cursor),数据放在内存中,直接操作。跟Mongo shell 一样指针操作。

         6、db.collection.aggregate()输出的结果只能保存在一个文档中,BSON Document大小限制为16M。可以通过返回指针解决,版本2.6中后面:DB.collect.aggregate()方法返回一个指针,可以返回任何结果集的大小。

         

 

 二、aggregate语法:

 

      db.collection.aggregate(pipeline, options)

 

     【pipeline  $group参数】

 

         pipeline 类型是Array  语法: db.collection.aggregate( [ { <stage> }, ... ] ) 

       $group : 将集合中的文档分组,可用于统计结果,$group首先将数据根据key进行分组。

      $group语法: { $group: { _id: <expression>, <field1>: { <accumulator1> : <expression1> }, ... } }

          _id 是要进行分组的key

       $group:可以分组的数据执行如下的表达式计算:

           $sum:计算总和。

           $avg:计算平均值。

           $min:根据分组,获取集合中所有文档对应值得最小值。

           $max:根据分组,获取集合中所有文档对应值得最大值。

           $push:将指定的表达式的值添加到一个数组中。

           $addToSet:将表达式的值添加到一个集合中(无重复值)。

           $first:返回每组第一个文档,如果有排序,按照排序,如果没有按照默认的存储的顺序的第一个文档。

           $last:返回每组最后一个文档,如果有排序,按照排序,如果没有按照默认的存储的顺序的最后个文档。

 

     我们可以通过Aggregation pipeline一些使用跟sql用法一样,我们能很清晰的怎么去使用

 

           pipeline                                           sql

           $avg                                                 avg

           $min                                                min

           $max                                               max 

           $group                                             group by

           $sort                                               order by

           $limit                                               limit                   

           $sum                                              sum()

           $sum                                              count()

 

   三、pipeline $group 简单的例子

 

      【数据 】 

 

[sql] view plain copy

 在CODE上查看代码片派生到我的代码片

  1. db.items.insert( [  
  2.   {  
  3.    "quantity" : 2,  
  4.    "price" : 5.0,  
  5.    "pnumber" : "p003",  
  6.   },{  
  7.    "quantity" : 2,  
  8.    "price" : 8.0,  
  9.    "pnumber" : "p002"  
  10.   },{  
  11.    "quantity" : 1,  
  12.    "price" : 4.0,  
  13.    "pnumber" : "p002"  
  14.   },{  
  15.    "quantity" : 2,  
  16.    "price" : 4.0,  
  17.    "pnumber" : "p001"  
  18.   },{  
  19.    "quantity" : 4,  
  20.    "price" : 10.0,  
  21.    "pnumber" : "p003"  
  22.   },{  
  23.    "quantity" : 10,  
  24.    "price" : 20.0,  
  25.    "pnumber" : "p001"  
  26.   },{  
  27.    "quantity" : 10,  
  28.    "price" : 20.0,  
  29.    "pnumber" : "p003"  
  30.   },{  
  31.    "quantity" : 5,  
  32.    "price" : 10.0,  
  33.    "pnumber" : "p002"  
  34.   }  
  35. ])       

 

 

    【$group】

 

      1、将集合中的文档分组,可用于统计结果,$group首先将数据根据key进行分组。

             _id 是要进行分组的key,如果_id为null  相当于select  count(*) from table

 

  【 $sum】  

     1、 我们统计items有几条,相当于SQL:  select count(1) as count from items

 

 

[sql] view plain copy

 在CODE上查看代码片派生到我的代码片

  1. > db.items.count()  
  2. 8  
  3. > db.items.aggregate([{$group:{_id:null,count:{$sum:1}}}])  
  4. "_id" : null"count" : 8 }  

 

 

    2、我们统计一下数量,相当于SQL: select sum(quantity) as total  from  items

 

[sql] view plain copy

 在CODE上查看代码片派生到我的代码片

  1. > db.items.aggregate([{$group:{_id:null,total:{$sum:"$quantity"}}}])  
  2. "_id" : null"total" : 36 }  

 

 

  3、我们通过产品类型来进行分组,然后在统计卖出的数量是多少,相当于SQL:select sum(quantity) as total from  items  group by pnumber

 

[sql] view plain copy

 在CODE上查看代码片派生到我的代码片

  1.   > db.items.aggregate([{$group:{_id:"$pnumber",total:{$sum:"$quantity"}}}])  
  2. "_id" : "p001""total" : 12 }  
  3. "_id" : "p002""total" : 8 }  
  4. "_id" : "p003""total" : 16 }  

 

 

【$min 、 $max 】 

   1、我们通过相同的产品类型来进行分组,然后查询相同产品类型卖出最多的订单详情 ,相当于SQL: select max(quantity) as quantity from  items  group by pnumber

 

[sql] view plain copy

 在CODE上查看代码片派生到我的代码片

  1. > db.items.aggregate([{$group:{_id:"$pnumber",max:{$max:"$quantity"}}}])  
  2. "_id" : "p001""max" : 10 }  
  3. "_id" : "p002""max" : 5 }  
  4. "_id" : "p003""max" : 10 }  

 

 

    2、我们通过相同的产品类型来进行分组,然后查询相同产品类型卖出最多的订单详情 ,相当于SQL:select min(quantity) as quantity from  items  group by pnumber

 

[sql] view plain copy

 在CODE上查看代码片派生到我的代码片

  1. > db.items.aggregate([{$group:{_id:"$pnumber",min:{$min:"$quantity"}}}])  
  2. "_id" : "p001""min" : 2 }  
  3. "_id" : "p002""min" : 1 }  
  4. "_id" : "p003""min" : 2 }  

 

 

  3、我们通过相同的产品类型来进行分组,统计各个产品数量,然后获取最大的数量,相当于SQL: select max(t.total) from (select sum(quantity) as total from  items  group by pnumber) t

 

[sql] view plain copy

 在CODE上查看代码片派生到我的代码片

  1. > db.items.aggregate([{$group:{_id:"$pnumber",total:{$sum:"$quantity"}}}])  
  2. "_id" : "p001""total" : 12 }  
  3. "_id" : "p002""total" : 8 }  
  4. "_id" : "p003""total" : 16 }  
  5. > db.items.aggregate([{$group:{_id:"$pnumber",total:{$sum:"$quantity"}}},{$group:{_id:null,max:{$max:"$total"}}}])  
  6. "_id" : null"max" : 16 }  

 

 

【$avg】

    先根据$group,在计算平均值,只会针对数字的进行计算,会对字符串忽略

 

    1、我们通过相同的产品类型来进行分组,然后查询每个订单详情相同产品类型卖出的平均价格,相当于SQL:select avg(price) as price from  items  group by pnumber

 

[sql] view plain copy

 在CODE上查看代码片派生到我的代码片

  1.    
  2. > db.items.aggregate([{$group:{_id:"$pnumber",price:{$avg:"$price"}}}])  
  3. "_id" : "p001""price" : 12 }  
  4. "_id" : "p002""price" : 7.333333333333333 }  
  5. "_id" : "p003""price" : 11.666666666666666 }  

 

 

【$push】

      将指定的表达式的值添加到一个数组中,这个值不要超过16M,不然会出现错误

    1、我们通过相同的产品类型来进行分组,然后查询每个相同产品卖出的数量放在数组里面

 

[sql] view plain copy

 在CODE上查看代码片派生到我的代码片

  1. > db.items.aggregate([{$group:{_id:"$pnumber",quantitys:{$push:"$quantity"}}}])  
  2. "_id" : "p001""quantitys" : [ 2, 10 ] }  
  3. "_id" : "p002""quantitys" : [ 2, 1, 5 ] }  
  4. "_id" : "p003""quantitys" : [ 2, 4, 10 ] }  

[sql] view plain copy

 在CODE上查看代码片派生到我的代码片

  1. > db.items.aggregate([{$group:{_id:"$pnumber",quantitys:{$push:{quantity:"$quantity",price:"$price"}}}}])  
  2. "_id" : "p001""quantitys" : [ { "quantity" : 2, "price" : 4 }, { "quantity": 10, "price" : 20 } ] }  
  3. "_id" : "p002""quantitys" : [ { "quantity" : 2, "price" : 8 }, { "quantity": 1, "price" : 4 }, { "quantity" : 5, "price" : 10 } ] }  
  4. "_id" : "p003""quantitys" : [ { "quantity" : 2, "price" : 5 }, { "quantity": 4, "price" : 10 }, { "quantity" : 10, "price" : 20 } ] }  

 

 

【 $addToSet】

       将表达式的值添加到一个数组中(无重复值),这个值不要超过16M,不然会出现错误

 

[sql] view plain copy

 在CODE上查看代码片派生到我的代码片

  1. > db.items.aggregate([{$group:{_id:"$pnumber",quantitys:{$addToSet:"$quantity"}}}])  
  2. "_id" : "p001""quantitys" : [ 10, 2 ] }  
  3. "_id" : "p002""quantitys" : [ 5, 1, 2 ] }  
  4. "_id" : "p003""quantitys" : [ 10, 4, 2 ] }  

 

 

【 $first、 $last】

    $first:返回每组第一个文档,如果有排序,按照排序,如果没有按照默认的存储的顺序的第一个文档。

    $last:返回每组最后一个文档,如果有排序,按照排序,如果没有按照默认的存储的顺序的最后个文档。

 

[sql] view plain copy

 在CODE上查看代码片派生到我的代码片

  1. > db.items.aggregate([{$group:{_id:"$pnumber",quantityFrist:{$first:"$quantity"}}}])  
  2. "_id" : "p001""quantityFrist" : 2 }  
  3. "_id" : "p002""quantityFrist" : 2 }  
  4. "_id" : "p003""quantityFrist" : 2 }  


 

 

     我们这篇主要介绍了aggregate  pipeline的$group 基础操作,后续介绍了 pipeline其他参数和options使用

本文转载自:

LUIS1983
粉丝 4
博文 72
码字总数 79567
作品 0
深圳
私信 提问
MongoDB 3.6新功能先睹为快!

作者介绍 上海小胖,中国第十五位MONGODB PROFESSIONAL获得者,资深Python开发、DBA。DevOps践行者,曾独立开发Web服务平台,电商爬虫系统、运维管理系统,涵盖数据热力图、核心数据监控、服...

上海小胖
2017/11/13
0
0
MongoDB 4.0 首个 RC 版发布,支持多文档事务

MongoDB 因其灵活的文档模型、可扩展分布式设计广受开发者喜爱,在此基础上,MongoDB 4.0 推出了更强大的功能支持,目前 4.0 第一个 RC 版本已经发布。 开始体验 MongoDB 4.0 RC:下载地址 ...

局长
2018/06/05
2.2K
5
MongoDB Plugin 1.0.8,支持 3.4.0 及地理位置

MongoDB Plugin 1.0.8 发布了。 驱动 1.0.8 版本中 Mongodb Plugin 的依赖驱动跟随官方升级到最新的 3.4.0 版本。以下简称 plugin MongoDB 在 3.4 版本增加了大量的 aggregation 操作符,功能...

tbaby
2016/12/21
2.2K
1
PHP-mongo-php-library使用

上文地址:https://www.jianshu.com/p/1de642b956f7 接下来,我就按照这个官方包来给大家演示一遍基本的curd,我附带上原生的mongodb语句,以便大家理解 注明:我用的MongoDB版本为3.4. 打开任意一...

DullCat
2018/05/16
0
0
sql和mongodb基本操作对比

基本概念对比 SQL Terms/Concepts MongoDB Terms/Concepts database database table collection row document or BSON document column field index index table joins embedded documents a......

penngo
2014/03/20
510
0

没有更多内容

加载失败,请刷新页面

加载更多

Phpstorm2018 永久激活

1、安装phpstorm,安装包请自行官网下载 http://www.jetbrains.com/phpstorm/download/ 2、下载JetbrainsCrack.jar文件,存放至你的phpstorm执行文件同级目录下 下载JetbrainsCrack.jar 提取...

happyfish319
16分钟前
3
0
谈一谈Android进程间通信的几种方式

###来看一下Android中除了AIDL还有哪些进程间通信的方式: 1、Bundle Bundle实现了Parcelable,所以在Android中我们可以通过Intent在不同进程间传递Bundle数据。 但是在Intent 传输数据的过程...

二营长的意大利炮手
17分钟前
6
0
互联网薪资“高开低走”,你的能力是否真的可以匹配高薪?

对于国内外主流互联网大厂,技术出身似乎已经成为各大掌门人的必备标签。谷歌 CEO 桑达尔·皮查伊、马克·扎克伯格、李彦宏、马化腾、雷军等等皆为技术人出身,都曾参与了公司内部重要产品的...

Java技术剑
18分钟前
6
0
java 多线程

线程声明周期 线程的五个状态:新建,就绪,运行,阻塞,死亡。 其中就绪和运行两个状态客户互相转换,但运行到阻塞,阻塞到就绪,只能单向转换。 刚new出的线程就是【新建】状态,调用start...

雷开你的门
20分钟前
6
0
构造器Constructor是否可被overrid

构造器不能被重写,不能用static修饰构造器,只能用public private protected这三个权限修饰符,且不能有返回语句。

无名氏的程序员
24分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部