zoukankan      html  css  js  c++  java
  • MongoDB聚合(单一用途的聚合方法)

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

    聚合指各种可以处理批量记录并返回计算结果的操作,并MongoDB提供了丰富的聚合操作,MongoDB提供了进行聚合的三种方式:聚集管道(Aggregation),Map-Reduce方法,和单一用途的聚合方法。

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

          一:db.collection.count()  返回匹配查询结果的数量

              db.collection.count(query, options)  返回匹配查询结果的数量  相当于mysql的语法:select count(1) 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.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:过滤条件,根据条件过滤集合的文档。
      
          2、完成器【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 } ]  
    34.        


           MongoDB提供了进行聚合的三种方式:聚集管道(Aggregation),Map-Reduce方法,和单一用途的聚合方法,先介绍了单一用途的聚合方法的使用方法,接下去介绍聚集管道(Aggregation)和Map-Reduce方法。
  • 相关阅读:
    Ajax ToolKit ModelPopupExtender报错:Sys.InvalidOperationException: Handler was not added through the Sys.UI.DomE
    C# 注释 类头部
    matlab练习程序(图像滤波时的边界处理2)
    更改chrome默认搜索引擎
    matlab练习程序(表面模糊)
    matlab练习程序(三阶张量TQR分解)
    linux命令行关机
    matlab练习程序(奇异值分解压缩图像)
    matlab练习程序(方框模糊)
    matlab练习程序(图像滤波时的边界处理)
  • 原文地址:https://www.cnblogs.com/yanwei-wang/p/8615988.html
Copyright © 2011-2022 走看看