一、aggregate執行流程和特性
1、執行流程:
db.collection.aggregate()是基於數據處理的聚合管道,每個文檔通過一個由多個階段(stage)組成的管道,可以對每個階段的管道進行分組、過濾等功能,然后經過一系列的處理,輸出相應的結果;
下圖來自官方文檔截圖,作為aggregate運行過程圖,方便大家了解;

2、特性:
db.collection.aggregate();
-
- 可以進行多管道操作,能方便進行數據處理;
- 使用了mongodb內置的原生sql操作,聚合效率非常高,支持類似於mysql中的group by功能;
- 每個階段管道限制為100MB的內存。如果一個節點管道超過這個極限,MongoDB將產生一個錯誤。為了能夠在處理大型數據集,可以設置allowDiskUse為true來在聚合管道節點把數據寫入臨時文件。這樣就可以解決100MB的內存的限制;
- 可以作用在分片集合,但結果不能輸在分片集合,MapReduce可以 作用在分片集合,結果也可以輸在分片集合
- 方法可以返回一個指針(cursor),數據放在內存中,直接操作。跟Mongo shell 一樣指針操作;
- 輸出的結果只能保存在一個文檔中,BSON Document大小限制為16M。可以通過返回指針解決,版本2.6中后面:DB.collect.aggregate()方法返回一個指針,可以返回任何結果集的大小;
二、aggregate語法: db.collection.aggregate(pipeline, options)
[pipeline參數]
$group : 將集合中的文檔分組,可用於統計結果,$group首先將數據根據key進行分組;
$project:可以對輸入文檔進行添加新字段或刪除現有的字段,可以自定哪些字段顯示與不顯示;
$match :根據條件用於過濾數據,只輸出符合條件的文檔,如果放在pipeline前面,根據條件過濾數據,傳輸到下一個階段管道,可以提高后續的數據處理效率。還可以放在out之前,對結果進行再一次過濾;
$redact :字段所處的document結構的級別;
$limit :用來限制MongoDB聚合管道返回的文檔數;
$skip :在聚合管道中跳過指定數量的文檔,並返回余下的文檔;
$unwind :將文檔中的某一個數組類型字段拆分成多條,每條包含數組中的一個值;
$sample :隨機選擇從其輸入指定數量的文檔。如果是大於或等於5%的collection的文檔,$sample進行收集掃描,進行排序,然后選擇頂部的文件。因此,$sample 在收集階段是受排序的內存限制 語法:{ $sample: { size: <positive integer> } }
$sort :將輸入文檔排序后輸出;
$geoNear:用於地理位置數據分析;
$out :必須為pipeline最后一個階段管道,因為是將最后計算結果寫入到指定的collection中;
$indexStats :返回數據集合的每個索引的使用情況;語法:{ $indexStats: { } }
[pipeline例子]
插入test數據(紅色區域表示插入成功)

[$group]
_id 是要進行分組的key,如果_id為null 相當於select count(*) from table;
$sum:
統計test_order表條數 == 'select count(*) as count from test_order';

統計test_order表 order_price總和 == 'select sum(order_price) as total_order_price from test_order';

統計test_order表不同訂單的order_price總和 == 'select sum(order_price) as total_order_price from test_order group by order_type';

$min、$max :
統計test_order表中order_price最大價格和最小價格,不同訂單的最大值和最小值 == 'select max(order_price) as order_type_max_price from test_order group by order_type';

$avg
統計test_order表中order_price平均價格 和不同訂單的平均價格 == 'select avg(order_price) as order_type_avg_price from test_order group by order_type';

$push、$addToSet
列舉出test_order表中不同類型的訂單價格 數據都不要超出16M

$first、$last
統計test_order表中不同訂單的第一條和最后一條的訂單價格(如果有排序則按照排序,如果沒有取自然first和last)

[$project]
根據需求去除test_order不需要展示的字段

[$match]
查詢不同訂單售賣的總價格,其中總價格大於100的== 'select sum(order_price) as order_type_sum_price from test_order group by order_price having order_type_sum_price > 100';

查詢order_type=3的總價 = 'select sum(order_price) as total_price' from test_order where order_type = 3';

[$limit、$skip]
查詢限制條數,和跳過條數可以使用在階段管道用在$group 之前可以大大的提高查詢性能

[$unwind]
可以拆分數組類型字段,其中包含數組字段值

[$out]
是把執行的結果寫入指定數據表中

[options例子]
explain:返回指定aggregate各個階段管道的執行計划信息

