MongoDB聚合(單一用途的聚合方法)

轉自:http://blog.csdn.net/congcong68/article/details/51419231  javascript

聚合指各類能夠處理批量記錄並返回計算結果的操做,並MongoDB提供了豐富的聚合操做,MongoDB提供了進行聚合的三種方式:彙集管道(Aggregation),Map-Reduce方法,和單一用途的聚合方法。java

       單一用途的聚合方法:db.collection.count(), db.collection.group(), db.collection.distinct()。mysql

 

      一:db.collection.count()  返回匹配查詢結果的數量

          db.collection.count(query, options)  返回匹配查詢結果的數量  至關於mysql的語法:select count(1) from orders where 條件。sql

          

[sql]  view plain  copy
 
  1. > db.orders.find()  
  2. "_id" : ObjectId("57383f492bd2092c7ed0fec7"), "ino" : "001", "quantity" : 2, "  
  3. price" : 4 }  
  4. "_id" : ObjectId("57383f492bd2092c7ed0fec8"), "ino" : "002", "quantity" : 2, "  
  5. price" : 6 }  
  6. "_id" : ObjectId("57383f492bd2092c7ed0fec9"), "ino" : "003", "quantity" : 3, "  
  7. price" : 5 }  
  8. > db.orders.count()  
  9. 3  
  10.   
  11. > db.orders.count({quantity:{$gt:2}})  
  12. 1  

 

      也能夠這樣獲取返回匹配查詢結果的數量:數據庫

      var cursor=db.items.find()  能夠以查詢只包含索引鍵的條件,  cursor.count()。數組

   二: db.collection.distinct()  返回某個字段的非重複值列表

       db.collection.distinct(field, query)  返回指定某個字段的非重複的值的列表,結果不能大於最大BSON大小(大小爲4 MB)    至關於mysql的語法:select distinct(field) from orders where 條件。
 
[sql]  view plain  copy
 
  1. > db.orders.find()  
  2. "_id" : ObjectId("57383f492bd2092c7ed0fec7"), "ino" : "001", "quantity" : 2, "  
  3. price" : 4 }  
  4. "_id" : ObjectId("57383f492bd2092c7ed0fec8"), "ino" : "002", "quantity" : 2, "  
  5. price" : 6 }  
  6. "_id" : ObjectId("57383f492bd2092c7ed0fec9"), "ino" : "003", "quantity" : 3, "  
  7. price" : 5 }  
  8. > db.orders.distinct("quantity")  
  9. [ 2, 3 ]  

    三: db.collection.group()  

      db.collection.group({ key, reduce, initial[, keyf] [, cond] [, finalize] })
 
      咱們比較熟悉的group by 的sql語句select key from table  group by key,而mongoDB沒提供SQL那樣經過group By就輕鬆實現數據庫的分組功能, db.collection.group()是對某個字段的對集合進行分組,而後經過聚合每一組中的全部文檔,能夠對聚合每一組中的全部文檔進行處理,來產生最終的咱們想要的結果文檔。
       db.collection.group()使用JavaScript,它受到了一些性能上的限制。大多數狀況下,$ group在Aggregation Pipeline提供了一種具備較少的限制適用的替代。能夠經過指定的鍵的集合中的文檔和執行簡單的聚合函數。
         (1)在2.2版本中,返回的數組能夠包含最多20000個元素;即最多20000個獨特的分組。
         (2)彙集管道(Aggregation),Map-Reduce方法均可以運行在分片集合,group()方法不能運行在分片集羣中工做。 
         (3)結果集必須符合最大BSON文檔大小(大小爲4 MB)。
 
 1. 訂單集合記錄日期和明細中的數量、產品編碼,咱們訂單集合按照對日期和產品編碼進行分組字段,而後對每一組文檔進行處理,找出並計算相同的產品的數量。Sql語句:Select pnumber,sum(quantity) as total from orders,items group by pnumber(少了兩張表的關聯的條件)。
      
[sql]  view plain  copy
 
  1. > db.orders.find()  
  2. "_id" : ObjectId("573848342bd2092c7ed0feca"), "onumber" : "001", "date" : ISOD  
  3. ate("2014-01-02T16:03:00Z"), "cname" : "zcy", "item" : { "quantity" : 2, "price"  
  4.  : 5, "pnumber" : "p003" } }  
  5. "_id" : ObjectId("573848342bd2092c7ed0fecb"), "onumber" : "002", "date" : ISOD  
  6. ate("2014-01-03T16:03:00Z"), "cname" : "zcy", "item" : { "quantity" : 1, "price"  
  7.  : 4, "pnumber" : "p002" } }  
  8. "_id" : ObjectId("573848342bd2092c7ed0fecc"), "onumber" : "003", "date" : ISOD  
  9. ate("2014-01-04T16:03:00Z"), "cname" : "zcy", "item" : { "quantity" : 10, "price  
  10. " : 2, "pnumber" : "p001" } }  
  11. "_id" : ObjectId("573848342bd2092c7ed0fecd"), "onumber" : "003", "date" : ISOD  
  12. ate("2014-01-04T16:03:00Z"), "cname" : "zcy", "item" : { "quantity" : 30, "price  
  13. " : 4, "pnumber" : "p002" } }  
  14. "_id" : ObjectId("573848342bd2092c7ed0fece"), "onumber" : "004", "date" : ISOD  
  15. ate("2014-01-05T16:03:00Z"), "cname" : "zcy", "item" : { "quantity" : 5, "price"  
  16.  : 4, "pnumber" : "p002" } }  
  17.    
  18. >  db.orders.group({  
  19. ...           key: {'item.pnumber':1},  
  20. ...           initial : {"total":0},  
  21. ...          reduce : function Reduce(doc, out) {  
  22. ...         out.total+=doc.item.quantity  
  23. ...    } });  
  24. [  
  25.         {  
  26.                 "item.pnumber" : "p003",  
  27.                 "total" : 2  
  28.         },  
  29.         {  
  30.                 "item.pnumber" : "p002",  
  31.                 "total" : 36  
  32.         },  
  33.         {  
  34.                 "item.pnumber" : "p001",  
  35.                 "total" : 10  
  36.         }  
  37. ]  
 
   描述:
     key:做爲分組的key。
     reduce:一個聚合函數操做文檔的分組操做期間。這些函數能夠返回一個sum或count。該函數接受兩個參數:當前  文檔和這個羣體彙集的結果文檔。
     initial:初始化聚合結果文檔變量,爲空時自動爲每列提供初始變量。
     keyf:可選。替代的key 字段。指定一個函數建立一個「key object」做爲分組的key。使用keyf而是經過group by領域而不是現有的文檔域鍵組。
     cond:過濾條件,根據條件過濾集合的文檔。
  
      二、完成器【finalize】
       
          咱們對finalize方法 進行詳細的介紹,在db.collection.group()返回最終結果以前,每一組文檔執行完後,多會觸發此方法,此功能能夠修改的結果文檔或替換的結果文檔做爲一個總體,執行group()結果集必須符合最大BSON文檔大小(大小爲4 MB),finalize能對數據傳到客戶時,進行裁剪結果,能夠提升很大的效率。
  
       (1) 咱們對訂單集合根據日期進行分組,並對相同的產品號數量進行累加,對累加完的產品數量沒有大於20 的咱們進行刪除。減小返回的數據。
            
         
[sql]  view plain  copy
 
  1. db.orders.group({  
  2.          key: {date:1},  
  3.          initial : {"pnumbers":{}},  
  4.          reduce : function Reduce(doc, out) {  
  5.  if(out.pnumbers[doc.item.pnumber]==null){  
  6.     out.pnumbers[doc.item.pnumber]=new Object();  
  7.     out.pnumbers[doc.item.pnumber]=doc.item.quantity;  
  8.  }else{  
  9.    out.pnumbers[doc.item.pnumber]+=doc.item.quantity;  
  10. }   
  11.         },finalize : function Finalize(doc) {  
  12.              for(i in doc.pnumbers)  
  13.           {  
  14.             if (doc.pnumbers[i] < 20)  
  15.              {  
  16.                  delete doc.pnumbers[i];  
  17.              }  
  18.            }  
  19.   } });  
  20.   
  21. [  
  22.       {  
  23.               "date" : ISODate("2014-01-02T16:03:00Z"),  
  24.               "pnumbers" : {  
  25.   
  26.               }  
  27.       },  
  28.       {  
  29.               "date" : ISODate("2014-01-03T16:03:00Z"),  
  30.               "pnumbers" : {  
  31.   
  32.               }  
  33.       },  
  34.       {  
  35.               "date" : ISODate("2014-01-04T16:03:00Z"),  
  36.               "pnumbers" : {  
  37.                       "p002" : 30  
  38.               }  
  39.       },  
  40.       {  
  41.               "date" : ISODate("2014-01-05T16:03:00Z"),  
  42.               "pnumbers" : {  
  43.   
  44.               }  
  45.       }  
    (2)每一組文檔執行完後,多會觸發此方法,此功能能夠修改的結果文檔,咱們對訂單的集合實現一天賣出了多少個產品,金額是多少,平均價格是多少。
     
     
[sql]  view plain  copy
 
  1.   db.orders.group({  
  2.      key: {date:1},  
  3.      initial :{"total":0,"money":0},  
  4.      reduce : function Reduce(doc, out) {  
  5.      out.total+=doc.item.quantity;  
  6.         out.money+=doc.item.quantity*doc.item.price;  
  7.       },  
  8.      finalize : function Finalize(out) {  
  9.        out.avg=out.money/out.total  
  10.        return out;  
  11.    }  
  12. });  
  13. [  
  14.       {  
  15.               "date" : ISODate("2014-01-02T16:03:00Z"),  
  16.               "total" : 2,  
  17.               "money" : 10,  
  18.               "avg" : 5  
  19.       },  
  20.       {  
  21.               "date" : ISODate("2014-01-03T16:03:00Z"),  
  22.               "total" : 1,  
  23.               "money" : 4,  
  24.               "avg" : 4  
  25.       },  
  26.       {  
  27.               "date" : ISODate("2014-01-04T16:03:00Z"),  
  28.               "total" : 40,  
  29.               "money" : 140,  
  30.               "avg" : 3.5  
  31.       },  
  32.       {  
  33.               "date" : ISODate("2014-01-05T16:03:00Z"),  
  34.               "total" : 5,  
  35.               "money" : 20,  
  36.               "avg" : 4  
  37.       }  
   3.keyf的使用
       能夠接受一個javascript函數,用來動態的肯定分組文檔的字段,和key二者必須有一個。咱們有時用到比較複雜的key時,能夠經過keyf的方法使用javascript函數對要進行分組的字段先進行特殊的處理,而後在作爲key進行分組。
 
     咱們對訂單集合,按照日期的月份進行分組,咱們保存的文檔的日期是到天,因此咱們先轉換爲月,並計算月份賣出了多少個產品,金額是多少,平均價格是多少。
 
 
[sql]  view plain  copy
 
  1.        
  2. > db.orders.find({})  
  3. "_id" : ObjectId("573848342bd2092c7ed0feca"), "onumber" : "001", "date" : ISOD  
  4. ate("2014-01-02T16:03:00Z"), "cname" : "zcy", "item" : { "quantity" : 2, "price"  
  5.  : 5, "pnumber" : "p003" } }  
  6. "_id" : ObjectId("573848342bd2092c7ed0fecb"), "onumber" : "002", "date" : ISOD  
  7. ate("2014-01-03T16:03:00Z"), "cname" : "zcy", "item" : { "quantity" : 1, "price"  
  8.  : 4, "pnumber" : "p002" } }  
  9. "_id" : ObjectId("573848342bd2092c7ed0fecc"), "onumber" : "003", "date" : ISOD  
  10. ate("2014-01-04T16:03:00Z"), "cname" : "zcy", "item" : { "quantity" : 10, "price  
  11. " : 2, "pnumber" : "p001" } }  
  12. "_id" : ObjectId("573848342bd2092c7ed0fecd"), "onumber" : "003", "date" : ISOD  
  13. ate("2014-01-04T16:03:00Z"), "cname" : "zcy", "item" : { "quantity" : 30, "price  
  14. " : 4, "pnumber" : "p002" } }  
  15. "_id" : ObjectId("573848342bd2092c7ed0fece"), "onumber" : "004", "date" : ISOD  
  16. ate("2014-01-05T16:03:00Z"), "cname" : "zcy", "item" : { "quantity" : 5, "price"  
  17.  : 4, "pnumber" : "p002" } }  
  18. >  db.orders.group({  
  19. ...    keyf: function (doc){  
  20. ...    return{'month':doc.date.getMonth()+1};  
  21. ...  },  
  22. ...  initial :{"total":0,"money":0},  
  23. ...  reduce : function Reduce(doc, out) {  
  24. ...     out.total+=doc.item.quantity;  
  25. ...           out.money+=doc.item.quantity*doc.item.price;  
  26. ...  
  27. ... },  
  28. ...  finalize : function Finalize(out) {  
  29. ...          out.avg=out.money/out.total  
  30. ...          return out;  
  31. ...   }  
  32. ... });  
  33. [ { "month" : 1, "total" : 48, "money" : 174, "avg" : 3.625 } ]  
       MongoDB提供了進行聚合的三種方式:彙集管道(Aggregation),Map-Reduce方法,和單一用途的聚合方法,先介紹了單一用途的聚合方法的使用方法,接下去介紹彙集管道(Aggregation)和Map-Reduce方法。
相關文章
相關標籤/搜索