
[英]MapReduce in MongoDB doesn't reduce all the k-v pairs with the same key in one go
[英]MongoDB MapReduce - Emit one key/one value doesnt call reduce
所以我是mongodb和mapreduce的新手,并且遇到了这个“怪癖”(或者至少在我看来是个怪癖)
假设我的集合中有对象如下:
{'key':5,'value':5}
{'key':5,'value':4}
{'key':5,'value':1}
{'key':4,'value':6}
{'key':4,'value':4}
{'key':3,'value':0}
我的地图功能只是发出键和值
我的reduce函数只是在返回它们之前添加了值AND并添加1(我这样做是为了检查是否甚至调用了reduce函数)
我的结果如下:
{'_ id':3, '值':0 }
{'_ id':4,'价值':11.0}
{'_ id':5,'价值':11.0}
正如你所看到的,对于键4和5,我得到了键3的预期答案11 BUT(在该键的集合中只有一个条目)我得到了意想不到的0!
这是mapreduce的一般自然行为吗? 对于MongoDB? 对于pymongo(我正在使用)?
reduce函数将具有相同键的文档合并到一个文档中。 如果map函数为特定键发出单个文档(与键3的情况一样),则不会调用reduce函数。
我意识到这是一个较老的问题,但我来到它并觉得我仍然不明白为什么这种行为存在以及如何构建map / reduce功能因此它不是问题。
MongoDB如果存在单个键实例则不调用reduce函数的原因是因为没有必要(我希望这会在一瞬间更有意义)。 以下是减少功能的要求 :
- reduce函数必须返回一个对象,其类型必须与 map函数发出的值的类型相同 。
- valuesArray中元素的顺序不应影响reduce函数的输出
- reduce函数必须是幂等的。
第一个要求是非常重要的,似乎很多人都忽略了它,因为我已经看到一些人在reduce函数中映射然后处理finalize函数中的单键情况。 然而,这是解决问题的错误方法。
想想这样:如果只有一个键的实例,一个简单的优化是完全跳过reducer(没有什么可以减少)。 单键值仍包含在输出中,但reducer的目的是在集合中构建多键文档的聚合结果。 如果mapper和reducer输出的是同一类型,那么通过查看map / reduce函数输出的对象结构 ,你应该没有意识到。 您不必使用finalize函数来更正未通过reducer运行的对象的结构。
简而言之,在map函数中进行映射,并将多键值减少为reduce函数中的单个聚合结果。
解:
在finalize中检查此字段并执行必要的操作
$map = new MongoCode("function() { var value = { time: this.time, email_id: this.email_id, single: 0 }; emit(this.email, value); }"); $reduce = new MongoCode("function(k, vals) { // make some need actions here return { time: vals[0].time, email_id: vals[0].email_id, single: 1 }; }"); $finalize = new MongoCode("function(key, reducedVal) { if (reducedVal.single == 0) { reducedVal.time = 11111; } return reducedVal; };");
“MongoDB不会为只有一个值的键调用reduce函数.values参数是一个数组,其元素是”映射“到键的值对象。”
http://docs.mongodb.org/manual/reference/command/mapReduce/#mapreduce-reduce-cmd
这是mapreduce的一般自然行为吗?
是。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.