我们的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
。然后使用每个数组的长度来确定当天有多少注册。
然而,虽然结果大多是正确的,但也存在明显的不准确之处。例如,当我们知道实际数字要高得多时,第一天给了我们两位数的值。尽管对相同的数据进行操作,但第二次运行 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" })
令我们惊讶的是,这为之前错误的每个日期提供了正确的结果。
有谁知道为什么第一次地图缩减没有按预期运行?
对于发出的值,可以多次调用Reduce,以后的调用将传递到早期调用的输出以进行reduce。 当您只查看数组的长度时,您会忽略可能正在查看部分聚合数据的事实。 对值求和将使较早的聚合累积,这是您想要的。