關注公衆號【Ccww筆記】,領取乾貨資料
MongoDB中聚合(aggregate) 操做未來自多個document的value組合在一塊兒,並經過對分組數據進行各類操做處理,並返回計算後的數據結果,主要用於處理數據(諸如統計平均值,求和等)。MongoDB提供三種方式去執行聚合操做:聚合管道(aggregation pipeline)、Map-Reduce函數以及單一的聚合命令(count、distinct、group)。mongodb
聚合管道是由aggregation framework將文檔進入一個由多個階段(stage)組成的管道,能夠對每一個階段的管道進行分組、過濾等功能,而後通過一系列的處理,輸出相應的聚合結果。如圖所示:數據庫
聚合管道操做:數組
db.orders.aggregate([ { $match: { status: "A" } }, { $group: { _id: "$cust_id", total: { $sum: "$amount" } } } ])
管道在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操做/函數 |
---|---|
$match | where |
$group | group by |
$match | having |
$project | select |
$sort | order by |
$limit | limit |
$sum | sum() |
$lookup | join |
管道序列優化化:
1).使用$projector/$addFields+$match 序列優化:當Aggregation Pipeline中有多個$projectior/$addFields階段和$match 階段時,會先執行有依賴的$projector/$addFields階段,而後會新建立的$match階段執行,以下,spa
{ $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 } } }
優化執行:code
{ $match: { name: "Joe Schmoe" } }, { $addFields: { maxTime: { $max: "$times" }, minTime: { $min: "$times" } } }, { $match: { maxTime: { $lt: 20 }, minTime: { $gt: 5 } } }, { $project: { _id: 1, name: 1, times: 1, maxTime: 1, minTime: 1, avgTime: { $avg: ["$maxTime", "$minTime"] } } }, { $match: { avgTime: { $gt: 7 } } }
2). $sort + $match 以及$project + $skip,當$sort/$project跟在$match/$skip以後時,會先執行$match/$skip後再執行$sort/$project,$sort以達到最小化需排列的對象數,$skip約束,以下:視頻
{ $sort: { age : -1 } }, { $match: { score: 'A' } } { $project: { status: 1, name: 1 } }, { $skip: 5 }
優化執行:
{ $match: { score: 'A' } }, { $sort: { age : -1 } } { $skip: 5 }, { $project: { status: 1, name: 1 } }
3). $redact+$match序列優化,當$redact後有$match時,可能會新創一個$match階段進行優化,以下,
{ $redact: { $cond: { if: { $eq: [ "$level", 5 ] }, then: "$$PRUNE", else: "$$DESCEND" } } }, { $match: { year: 2014, category: { $ne: "Z" } } }
優化執行:
{ $match: { year: 2014 } }, { $redact: { $cond: { if: { $eq: [ "$level", 5 ] }, then: "$$PRUNE", else: "$$DESCEND" } } }, { $match: { year: 2014, category: { $ne: "Z" } } }
還有不少管道序列優化能夠查看《官方文檔-Aggregation Pipeline Optimization》。
若是管道以$match精確分片 key開始的後,全部管道會在匹配的分片上進行。對於需運行在多分片中的聚合(aggregation)操做,若是不不須要在主分片進行的,這些操做後的結果會路由到隨機分片中進行合併結果,避免重載該主分片的數據庫。$out和$look階段必須在主分片數據庫運行。
MongoDB還提供map-reduce操做來執行聚合。 一般,map-reduce操做有兩個階段:一個map階段,它處理每一個文檔併爲每一個輸入文檔發出一個或多個對象,以及reduce階段組合map操做的輸出。 可選地,map-reduce能夠具備最終化階段以對結果進行最終修改。 與其餘聚合操做同樣,map-reduce能夠指定查詢條件以選擇輸入文檔以及排序和限制結果。
Map-reduce使用自定義JavaScript函數來執行映射和減小操做,以及可選的finalize操做。 雖然自定義JavaScript與聚合管道相比提供了極大的靈活性,但一般,map-reduce比聚合管道效率更低,更復雜。模式以下:
MongoDB還提供了,db.collection.estimatedDocumentCount(),db.collection.count()和db.collection.distinct()
全部這些單一的聚合命令。 雖然這些操做提供了對常見聚合過程的簡單訪問操做,但它們缺少聚合管道和map-reduce的靈活性和功能。模型以下
可以使用MongoDB中聚合操做用於數據處理,能夠適應於一些數據分析等,聚合的典型應用包括銷售數據的業務報表,好比將各地區的數據分組後計算銷售總和、財務報表等。最後想要更加深刻理解還須要本身去實踐。
最後可關注公衆號【Ccww筆記】,一塊兒學習,天天會分享乾貨,還有學習視頻乾貨領取!