MongoDB聚合函数

MongoDB聚合函数

在关系数据库中,我们可以在数值型字段上执行包含预定义聚合函数的SQL语句,比如,SUM()、COUNT()、MAX()和MIN()。但是在MongoDB中,需要通过MapReduce功能来实现聚合以及批处理,它跟SQL里用来实现聚合的GROUP BY从句比较类似。下一节将描述关系数据库中SQL方式实现的聚合和相应的通过MongoDB提供的MapReduce实现的聚合。

1、count

count返回集合中的文档数量

  • SQL 代码   复制
  • 
    
    			db.refactor.count() 
    
    //不管集合有多大,都能很快的返回文档数量.可以传递查询,MongoDB会计算查询结果的数量
    
    db.refactor.count({"username":"refactor"}) 
    
    //但是增加查询条件会使count变慢.
    
  •     

    2、distinct

    distinct用来找出给定键的所有不同值.使用时必须指定集合和键.

  •  
  • SQL 代码   复制
  • 
    db.runCommand({"distinct":"refactor","key":"username"}) 
    		
  •      

    3、group

    group先选定分组所依据的键,MongoDB将会将集合依据选定键值的不同分成若干组.然后可以通过聚合每一组内的文档,产生一个结果文档.

  •  
  • SQL 代码   复制
  • 
    
    //"ns":"refactor",指定要进行分组的集合
    //"key":{"username":true},指定文档分组的依据,这里是username键,所有username键的值相等的被划分到一组,true为返回键username的值
    //"initial":{"count":0},每一组reduce函数调用的初始个数.每一组的所有成员都会使用这个累加器.
    //"$reduce":function(doc,prev){...}每个文档都对应的调用一次.系统会传递两个参数:当前文档和累加器文档.
    //"condition":{"age":{"$gt":40}} 这个age的值大于40的条件
    
    db.runCommand({ 
    "group": 
       { 
        "ns":"refactor", 
        "key":{"username":true}, 
        "initial":{"count":0}, 
        "$reduce":function(doc,prev) { prev.count++;
         }, 
        "condition":{"age":{"$gt":40}} 
        } 
       } )  
    		
  •    

    4、MapReduce

    count,distinct,group能做的事情MapReduce都能做.它是一个可以轻松并行化到多个服务器的聚合方法.它会拆分问题,再将各个部分发送到不同机器上,让每台机器完成一部分.当所有机器都完成时候,再把结果汇集起来形成最终完整的结果.

    MapReduce需要几个步骤:

    1.映射,将操作映射到集合中的每个文档.这个操作要么什么都不做,要么 产生一个键和n个值.

    2.洗牌,按照键分组,并将产生的键值组成列表放到对应键中.

    3.化简,把列表中的值 化简 成一个单值,这个值被返回.

    4.重新洗牌,直到每个键的列表只有一个值为止,这个值就是最终结果.

    MapReduce的速度比group慢,group也很慢.在应用程序中,最好不要用MapReduce,可以在后台运行MapReduce

    创建一个保存结果的集合,可以对这个集合进行实时查询.

    例如

  •  
  • SQL 代码   复制
  • 
    map=function(){ for(var key in this) { emit(key,{count:1}) } }; 
    
    //这样返回了许许多多的{count:1}文档,每一个都与集合中的一个键相关.这种有一个或多个{count:1}文档组成的数组,会传递给reduce函数.reduce函数有两个参数,一个是key,也就是emit返回的第一个值,另一个参数是数组,由一个或者多个对应键的{count:1}文档组成.
    
    reduce=function(key,emits)
            { 
              total=0; 
              for(var i in emits)
                 { 
                   total+=emits[i].count; 
                 } 
            return {count:total}; 
            }
    
    //reduce要能被反复被调用,不论是映射环节还是前一个化简环节.reduce返回的文档必须能作为reduce的第二个参数的一个元素.如x键映射到了3个文档
    
    {"count":1,id:1},{"count":1,id:2},{"count":1,id:3}
    
    //其中id键用于区别.
    
    //reduce应该能处理emit文档和其他reduce结果的各种集合.
    
    mr=db.runCommand( { 
    "mapreduce":"refactor",
    "map":map,
    "reduce":reduce,
    "out":{inline:1}
     } ) 
    
    或:
    
    db.refactor.mapReduce(map,reduce,{out:{inline:1}})
    
    		
  •    

    MapReduce中的其他键

    mapreduce,map,reduce这三个键是必须的,MapReduce命令还有其他的可选键

    finalize:函数

    将reduce的结果发送给这个键,这是处理过程的最后一步

    keeptemp:布尔值

    连接关闭时,临时结果是否保存

    output:字符串

    结果集合的名字,设定该项则隐含着keeptemp:true

    query:文档

    会在发往map函数前,先用指定条件过滤文档

       

    sort:文档

    会在发往map函数前先给文档排序

    limit:整数

    发往map函数文档的最大数量

       

    scope:文档

    javascript代码中要用到的变量

       

    verbose:布尔值

    是否产生更加信息的服务器日志

    标签: