我们的 MongoDB 数据库包含所有用户帐户的列表,其中每个新注册在帐户文档中都有一个“created_at”字段,其中包含创建它的当前日期和时间。
我们想知道每天有多少新注册,所以将一个 MapReduce 查询放在一起来为我们找到这个。
db.accounts.mapReduce(
function() {
var date = this.created_at.toLocaleDateString();
emit(date, 1);
},
function(key, values) {
return values.length;
},
{ out: "output" })
我们的第一次尝试在上面。对于每个注册,它都会为该日期发出值 1
。然后使用每个数组的长度来确定当天有多少注册。
然而,虽然结果大部分是正确的,但也存在明显的错误。例如,当我们知道实际数字要高得多时,第一天给了我们两位数的值(value)。尽管对相同的数据进行操作,但第二次运行 map reduce 函数后某些值发生了变化。
我们将函数更改为对数组的值求和(请记住,它应该只包含 1
,因此与 array.length
相同.
db.accounts.mapReduce(
function() {
var date = this.created_at.toLocaleDateString();
emit(date, 1);
},
function(key, values) {
var sum = 0;
for(var i = 0; i < values.length; i++) {
sum += values[i];
};
return sum;
},
{ out: "output" })
令我们惊讶的是,这给出了之前错误的每个日期的正确结果。
有谁知道为什么第一个 map reduce 没有按预期运行?
最佳答案
Reduce 可能会针对发出的值被多次调用,后面的调用会传递前面调用 reduce 的输出。当您只查看数组的长度时,您会错过您可能正在查看部分聚合数据的事实。对值求和将使较早的聚合累积,这就是您想要的。
关于javascript - 两个看似相同的 MapReduce 函数的令人费解的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10724284/