1. 程式人生 > >MongoDB聚合(Aggregation Pipeline基礎篇上

MongoDB聚合(Aggregation Pipeline基礎篇上

結果集 文檔 https set 閱讀 ins 聚合 sum() 2.6

學習MongoDB 十一: MongoDB聚合(Aggregation Pipeline基礎篇上)(三)
2016年06月09日 10:47:10
閱讀數:15320
一、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
db.items.insert( [
{
"quantity" : 2,
"price" : 5.0,
"pnumber" : "p003",
},{
"quantity" : 2,
"price" : 8.0,
"pnumber" : "p002"
},{
"quantity" : 1,
"price" : 4.0,
"pnumber" : "p002"
},{
"quantity" : 2,
"price" : 4.0,
"pnumber" : "p001"
},{
"quantity" : 4,
"price" : 10.0,
"pnumber" : "p003"
},{
"quantity" : 10,
"price" : 20.0,
"pnumber" : "p001"
},{
"quantity" : 10,
"price" : 20.0,
"pnumber" : "p003"
},{
"quantity" : 5,
"price" : 10.0,
"pnumber" : "p002"
}
])

【$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

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

2、我們統計一下數量,相當於SQL: select sum(quantity) as total  from  items

[sql] view plain copy

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

3、我們通過產品類型來進行分組,然後在統計賣出的數量是多少,相當於SQL:select sum(quantity) as total from items group by pnumber

[sql] view plain copy

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

【$min 、 $max 】

1、我們通過相同的產品類型來進行分組,然後查詢相同產品類型賣出最多的訂單詳情 ,相當於SQL: select max(quantity) as quantity from items group by pnumber

[sql] view plain copy

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

2、我們通過相同的產品類型來進行分組,然後查詢相同產品類型賣出最多的訂單詳情 ,相當於SQL:select min(quantity) as quantity from  items  group by pnumber

[sql] view plain copy

db.items.aggregate([{$group:{_id:"$pnumber",min:{$min:"$quantity"}}}])
{ "_id" : "p001", "min" : 2 }
{ "_id" : "p002", "min" : 1 }
{ "_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

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

【$avg】

先根據$group,在計算平均值,只會針對數字的進行計算,會對字符串忽略



1、我們通過相同的產品類型來進行分組,然後查詢每個訂單詳情相同產品類型賣出的平均價格,相當於SQL:select avg(price) as price from  items  group by pnumber

[sql] view plain copy

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

【$push】

  將指定的表達式的值添加到一個數組中,這個值不要超過16M,不然會出現錯誤

1、我們通過相同的產品類型來進行分組,然後查詢每個相同產品賣出的數量放在數組裏面

[sql] view plain copy

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

【 $addToSet】

   將表達式的值添加到一個數組中(無重復值),這個值不要超過16M,不然會出現錯誤

[sql] view plain copy

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

【 $first、 $last】
$first:返回每組第一個文檔,如果有排序,按照排序,如果沒有按照默認的存儲的順序的第一個文檔。

$last:返回每組最後一個文檔,如果有排序,按照排序,如果沒有按照默認的存儲的順序的最後個文檔。

[sql] view plain copy

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

 我們這篇主要介紹了aggregate  pipeline的$group 基礎操作,後續介紹了 pipeline其他參數和options使用

MongoDB聚合(Aggregation Pipeline基礎篇上