1. 程式人生 > >Mongodb聚合框架Aggregate

Mongodb聚合框架Aggregate

一 概念
  1、簡介
    mongo aggregation是mongo的一個輕量級的map-reduce框架,可以實現一些count,sum,group by的聚合。
    使用聚合框架可以對集合中的文件進行變換和組合。可以用多個構件建立一個管道,用於對一連串的文件進行處理。構件有:篩選、投射、分組、排序、限制和跳過。
    MongoDB的聚合管道將MongoDB文件在一個管道處理完畢後將結果傳遞給下一個管道處理,管道操縱是可以重複的。
  2、管道表示式
    管道操作符作為“鍵”,所對應的“值”叫做管道表示式。例如{$match:{status:”A”}},$match稱為管道操作符,而{status:”A”}稱為管道表示式,它可以看作是管道操作符的運算元(Operand),每個管道表示式是一個文件結構,它是由欄位名、欄位值、和一些表示式操作符組成的,例如管道表示式$group: { _id: null, count: { $sum: 1 } } 就包含了一個表示式操作符$sum進行累加求和。 
    每個管道表示式只能作用於處理當前正在處理的文件,而不能進行跨文件的操作。管道表示式對文件的處理都是在記憶體中進行的。除了能夠進行累加計算的管道表示式外,其他的表示式都是無狀態的,也就是不會保留上下文的資訊。累加性質的表示式操作符通常和$group操作符一起使用,來統計該組內最大值、最小值等。
  3、aggregate語法


    db.collection.aggregate(pipeline, options)
    pipeline:管道運算元組,也可以為文件型別,如果該引數不是陣列形式,無法指定options引數 
    options:aggregate命令的附加選項,文件型別。 
    1) explain:布林值,指定返回結果是否顯示該操作的執行計劃 
    2) allowDiskUse: 
    布林值,指定該聚合操作是否使用磁碟。每個階段管道限制為100MB的記憶體。如果一個節點管道超過這個極限,MongoDB將產生一個錯誤。為了能夠在處理大型資料集,可以設定allowDiskUse為true來在聚合管道節點把資料寫入臨時檔案。這樣就可以解決100MB的記憶體的限制。 
    3) cursor: 
    4) maxTimeMS: 
    5) bypassDocumentValidation: 
    6) readConcern: 
    7) collation:
  4、分片使用

    db.collection.aggregate()可以作用在分片集合,但結果不能輸在分片集合,MapReduce可以 作用在分片集合,結果也可以輸在分片集合。
  5、聚合中的遊標
    db.collection.aggregate()方法可以返回一個指標(cursor),資料放在記憶體中,直接操作。跟Mongo shell 一樣指標操作。

二 管道操作符
1、$match:用於對文件集合進行篩選,在$match中不能使用$geoNear地理空間操作符及$where表示式操作符。
    示例: 獲取分數大於70小於或等於90記錄,然後將符合條件的記錄送到下一階段$group管道操作符進行處理。
    db.articles.aggregate( [
     { $match : { score : { $gt : 70, $lte : 90 } } },
     { $group: { _id: null, count: { $sum: 1 } } }
    ]);
2、$project:

可以從子文件中提取欄位,可以重新命名欄位,可以移除欄位。
    示例: 獲取article集合的title欄位及author欄位,將欄位_id遮蔽
    db.article.aggregate({
      $project : {
        _id : 0 ,
        title : 1 ,
        author : 1
    }});
3、$group:操作可以根據文件特定欄位的不同值進行分組,$group不能用流式工作方式對文件進行處理。 在$group階段,記憶體的大小最大可以為100Mb,如果超過則會出錯。當處理大量資料是,可以將引數allowDiskUse置為true,如此$group操作符可以寫入臨時檔案,格式:
    { $group: { _id: <expression>,<field1>: { <accumulator1> : <expression1> }, … } }
    _id欄位是強制性的,可以指定其為空來進行其他累加操作,accumulator操作符可以為:$sum、$avg、$first、$last、$max、$min、$push、$addToSet、$stdDevPop、$stdDevSamp
    注:$group的輸出是無序的,且該操作目前是在記憶體中進行的,所以不能用它來對大量個數的文件進行分組。
 4、$unwind:分割陣列嵌入到自己頂層檔案,會將陣列中的每一個值拆分為單獨的文件,這樣一個文件會被分為陣列長度個文件。 
    示例:將部落格評論對映為cts並查詢評論作者為Mark的文件
    > db.blog.aggregate([
      {"project":{"cts":"$comments"}}, 
      {"$unwind":"$cts"},
      {"$match":{"cts.author":"Mark"}
    ]);
    注:{$unwind:”$cts”})不能忘了$符號,且如果$unwind目標欄位不存在的話,那麼該文件將被忽略過濾掉。
5、$limit:$limit會接受一個數字n,返回結果集中的前n個文件。
  { $limit: <positive integer> }
    示例:查詢5條文件記錄
    db.article.aggregate(
      { $limit : 5 }
    );
6、$skip:$skip接受一個數字n,丟棄結果集中的前n個文件 
  {$skip: <positive integer> } 
    示例:獲取article集合中第5條資料之後的資料
    db.article.aggregate(
      { $skip : 5 }
    );
7、$sort:可以根據任何欄位進行排序,”$sort”不能用流式工作方式對文件進行處理,必須要接收到所有文件之後才能進行排序。當排序的欄位BSON型別不一致時,按一下順序進行排序
 

官方參考文件:

The MongoDB 3.2 Manual:
https://docs.mongodb.com/v3.2/
Spring Data MongoDB - Reference Documentation
https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/