1

我正在尝试在 Mongo 中使用 mapReduce 来计算给定值出现的次数。

这是我的 map 函数,我在其中测试以确保每个值都是字符串:

function mapFunction () {
    function normalizeDate(date) {
        var day = date.getDay(),
        month = date.getMonth(),
        year = date.getYear();
        return new Date(year, month, day);
    }

    if (this.events.event.toString() === "[object Object]"
       || typeof(this.events.event) !== 'string') {
          throw new Error("Not a string...");
    }

    emit(normalizeDate(this.date), this.events.event);
}

为了完整起见,这是我的 reduce 函数:

function reduceFunction (date, event_arry) {
    return event_arry.reduce(function (a, b) {
    if (a[b]) {
        a[b]++;
    }
    else {
        a[b] = 1;
    }
    return a;
    }, {});
}

然后,我在 mongo repl 中运行 mapReduce:

mongos> db.events.mapReduce(mapFunction, reduceFunction, {out: 'mr_test'})
{
    "result" : "mr_test",
    "timeMillis" : 148,
    "counts" : {
        "input" : 3481,
        "emit" : 3481,
        "reduce" : 82,
        "output" : 14
    },
    "ok" : 1,
}

并且没有错误,表明所有的events 都是 type string

然而,当我查看mr_test集合中的输出时,我得到了几个这样的条目:

mongos> db.mr_test.find()
{ "_id" : ISODate("0113-04-05T00:00:00Z"), "value" : { "[object Object]" : 4 } }
{ "_id" : ISODate("0113-04-06T00:00:00Z"), "value" : { "[object Object]" : 5 } }
{ "_id" : ISODate("0113-04-30T00:00:00Z"), "value" : { "[object Object]" : 1, "eventTypeA" : 9, "eventTypeB" : 14, "eventTypeC" : 19 } }

对此有很好的解释吗?如果是这样,它是什么?

4

1 回答 1

2

对此有一个很好的解释(这与 99% 的 MongoDB mapreduce 问题相同。您的 map 值与您的 reduce 返回的格式不同。

您的 reduce 函数必须返回与 map 函数发出的相同格式。

你正在发出一个字符串,你希望得到一个文件!你需要做的是在你的 map 函数中最后发出你期望的确切格式:

emit(normalizeDate(this.date), {this.events.event:1} );

这表示:“对于特定的一天(键),我正在跟踪单个事件字符串,其总数为 1”。

然后调整您的reduce函数以迭代将其合并在一起的值数组,请记住,由于reduce函数可以多次调用(以重新减少特定键的结果),您“合并”或减少的文档可以是单个的{date:number} 或具有多个 {date1:number, date2: number, ... } 的复杂文档

于 2013-05-31T03:41:25.363 回答