主要介绍mapReduce在MongoDB中的使用,类似于sql的分组和聚合。首先对Map进行分组,然后使用reduce进行统计,最后可选地使用finalize来调整最终结果。好了,我来介绍一下,我用的版本是mongodb2.4.5,然后我也用MongoVUE(一个非常好的图形化mongodb管理工具)帮我配合。
1、原始数据,集合中有三个doc被使用:
它们的数据格式是:
可能很多人不关注mongodb中存储的数据格式,但对我来说,这是非常敏感的。我不喜欢在后台使用object来保存这些原本清晰的类型。我想在这里多提一点。如果使用控制台插入数据,插入的数字很可能保存为Double,但如果要保存为整数,就必须使用NumberInt()和NumberLong()。示例:
运行后,在控制台上看不到数据类型,但使用MongoVUE,我可以看到:
数据库直接保存为double。并使用:
可以保存为int32,使用NumberLong()保存为Int64。
2.让MapReduce实现多少人找不同名字的统计。首先是map函数,然后是reduce函数。
1函数Map() {2 emit(3 this.name,4 { count:1 } 5);6 }emit(key,value)是一个分组函数,指的是将原始单据按指定的key分组,value是从单据中取出的数据或者自己录入的数据,会加入到一个集合中(暂时称为C集合)。MapReduce将对每个文档进行Map函数调用,但是您可以决定是否使用emit函数对这些文档进行分组。没有分组的文档相当于被丢弃。不过我建议不要在Map函数中加入过滤操作,比如if (xxx==yyy) emit(.);相反,您应该在MapReduce之前查询以过滤掉信息(这将在后面讨论)。在地图功能中可以进行的过滤操作一般都是分类操作,比如分数高于60就按一定方式发射,低于60就按一定方式发射,而不是说高于60,否则什么都不做。
1 function Reduce(key,values) {2 var reduced={count:0,name:' ' };//初始化3 values . foreach(function(val){ 4 reduced . count=val . count的返回值;5 });6退货减少;7}接下来是Reduce函数,基于emit组的上述数据。函数的参数是key(上面emit中的key)和values(上面提到的C集)。MapReduce将为每个分组键调用一个Reduce函数。函数的第一行是初始化需要的统计结果数据,然后是你自己的统计方法,最后你需要返回这个结果。
好了,让我们看看如何在DB控制台下调用这个MapReduce:
1 db . run command({ MapReduce:' le kko '2 Map:function Map(){ 3 emit(4 this . name,5 { count:1 } 6);7 },8 reduce : function Reduce(key,values) { 9 var reduced={count:0,name:' ' };//初始化10个值的返回值。foreach (function (val) {11已减少。计数=val。数数;12 });13返回减少;14 },15 out:{ inline:1 } 16 });结果很快就出来了:
因为我之前在控制台下又添加了两个文档,所以现在有四个人叫lekko。值得注意的是,这里MapReduce后的结果将全部是double!
3.一些附加操作
MapReduce的简单原理很简单,关键是灵活运用。现在我举几个我自己经历的例子:
(1)将查询放入MapReduce。
在前面的runCommand中添加参数。比如我要查询所有男生,我就加.查询:{'isman' true},
(2)结果的数据类型转换。
使用Finalize函数(该函数在Reduce函数之后调用,它将对所有键的Reduce结果执行最终操作)。比如我想在后台调用api后得到int数据而不是double数据,那么我可以添加Finalize函数:
一.2 finalize:函数Finalize(key,reduced){ 3 reduced . count=number int(reduced . count);4退货减少;5 },6 .这样reduced的输出就会是int32,可以直接在后台使用强制转换,不用从object换成double再换成int(最好用ToString再用Prase作为强制转换)。
(3)时间类型
因为mongodb有日期类型,所以存储时间的格式和查询时间的格式可能会不一致(尤其是你的mongodb是远程部署,多人协作开发的时候),会导致无法根据时间条件找到数据的问题。我的建议是直接存储时间的长形式(过去的秒),那么这个差异问题就不复存在了。