mongo聚合

count

count可以返回集合的文档数量,也可以返回查询结果的数据:
db.foo.count();
db.foo.count({'key':'value'});

distinct

distinct会以数组的形式返回指定键的不同值:
db.people.distinct('name');

group

利用group可以将集合中的记录按一个或多个键分组,然后可以聚合每个分组内的文档产生新的结果。
比如我有一个商品列表,商品有类别(type),价格(price)两个字段,现在需要找出每类商品里最贵的商品值多少钱,看看利用group怎么实现:
db.product.group({'key':{'type':1},'$reduce':function(doc,prev){if(doc.price>prev.price) prev.price=doc.price},'initial':{'price':1}})
// runCommand命令
db.runCommand({'group':{'ns':'product','key':{'type':1},'$reduce':function(doc,prev){if(doc.price>prev.price) prev.price=doc.price},'initial':{'price':1}}})
返回结果:

传递给group工具的文档中包含的元素:
  • ns:指定集合;
  • key:分组的键;
  • initial:累加器初始值,分组之后,每一组的reduce函数会调用这个初始文档,并在组内传递累加器;
  • $reduce:分组处理函数,分组之后会对每组元素遍历处理,该函数两个参数,分别代表当前分组内的文档和传递的累加器,最后会输出累加器;

condition过滤

group还可以指定condition参数用于在分组处理前对文档进行过滤,比如,在上面的例子中只统计type为1,2,3的商品价格,那condition可以这样写:
db.product.group({'key':{'type':1},'$reduce':function(doc,prev){if(doc.price>prev.price) prev.price=doc.price},'initial':{'price':1},'condition':{'type':{'$in':[1,2,3]}}})

finalize完成器

finalize完成器用于对reduce函数生成的分组结果进行处理,比如在上面的例子中需要在价格数值前加上’$‘符号:
db.product.group({'key':{'type':1},'$reduce':function(doc,prev){if(doc.price>prev.price) prev.price=doc.price},'initial':{'price':1},'finalize':function(prev){prev.price='$'+prev.price}})
finalize函数的参数便是reduce函数输出的累加器。

keyf函数分组

有时候不能简单的用一个键进行分组,分组条件也许更复杂,比如上面的例子中,想把type为1和5的商品归为一类商品来统计,那可以如下这样做:
db.product.group({'$keyf':function(x){return {'type':x.type%4?x.type%4:4}},'$reduce':function(doc,prev){if(doc.price>prev.price) prev.price=doc.price},'initial':{'price':1}})
需要注意的是,$keyf函数必须返回一个对象。

MapReduce

MapReduce的功能类似于mysql中的group by,但它能很好的支持更复杂的统计需求。比如仍然拿上面的商品做例子,现在需要统计每一类商品的总数,实现的mapReduce如下:

db.product.mapReduce(function(){var key = this.type; emit(key,{count:1})},function(key,emits){total=0;for(var i in emits){total+=emits[i].count;}return {"count":total}},{out:'mr'})
mapReduce的原型为:function (map, reduce, optionsOrOutString),下面具体介绍一下函数的三个参数:

  • map函数,它会遍历集合中的每一个文档,this表示文档,它使用emit方法将文档按键分组,并返回需要统计的数据;
  • reduce函数,它将收集数据并统计,两个参数分别为map函数返回的key值和数据数组;
  • optionsOrOutString参数为一个对象,定义了一些额外工作,比如上面的列子中使用out参数将统计结果放入到mr集合中,集合不存在则创建,存在了则覆盖。

上面例子的输出结果为:

result表示结果放入的集合,可以通过命令db.mr.find()查看统计结果,timeMillis表示花费的时间,input表示map函数被调用的次数,emit表示emit方法调用的次数,reduce表示reduce函数调用的次数,output表示输出结果长度。

参数optionsOrOutString对象除了out键以外还有其它一些键:

  • finalize函数,同group的finalize完成器一样,可以对reduce的结果做一些处理;
  • query文档,在map函数前对文档过滤;
  • sort文档,在map函数前对文档排序,必须先对排序的字段建立索引;
  • limit整数,在map函数前设定文档数量;
  • scope文档,js函数中用到的变量,客户端可以通过scope传递一些值;
  • jsMode布尔,指定了map和reduce函数间传递的对象使用BSON格式还是javascript对象,默认值false,表示采用BSON格式,优点是中间的BSON数据会被存在硬盘上,所以传递的数据量可以很大,但会影响性能;采用javascript对象,性能较高,但只能传递50万个不同的key值;
  • verbos布尔,默认true,显示详细的时间统计信息。
可以看出MapReduce的强大,可以很轻松的实现不同的统计功能。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值