0

我看到使用 mongo 执行渐进式 map reduce 任务的令人困惑的行为。输入集合是一大组文档,其中包含:

{_id: , url: '来自我的时髦网站的一些 url'}

这是我的简单地图功能:

    map: function() {

        emit(this.url, {count: 1, id: this._id});

    }

和减少(有很多调试打印日志如下所示):

    reduce: function (key, values) {
        var count = 0;
        var lastId = null;
        var first = null;

        if (typeof values[0].id == "undefined") {
            print("bad id");
            printjson(key);
            printjson(values[0]);
            return null;
        } else {
            print ("good id");
            printjson(key);
            printjson(values[0]);
        }

        first = ObjectId(values[0].id).getTimestamp();

        values.forEach(function(v) {

            count += v.count;

            last = ObjectId(v.id).getTimestamp();

            lastId = v.id;

        });

        return {
            count: count, 
            first: first, 
            last: lastId, 
            lastCounted: lastId
        };
    }

以下是我如何调用 mapreduce:

        mrparams.out = {reduce: this.output};
        mrparams.limit = 100;

        mrparams.query = {'_id': {'$gt': mongoId(lastId.toHexString())}};
                    mrparams.finalize = null;


        mrdb.mapReduce(this.map, this.reduce, mrparams, function(d) {
            console.log("Finished mr", d);
            callback();
        });

这是以 cron 类型的方式完成的,因此每个时间间隔,作业都在限制数量的记录上运行,从上一次运行的 lastId之后的记录开始。

非常基本的增量地图减少的东西......

但是,当我运行它时,我看到 reduce 方法的返回值被传递回 reduce 方法。这是日志的快照:

XXXgood id " http://www.nytimes.com/2013/04/23/technology/germany-fines-google-over-data-collection.html " { "count" : 1, "id" : ObjectId("5175a065b25f029a1d0927e6 ") }

好身份证“ http://www.nytimes.com/2013/04/23/world/middleeast/israel-hagel-iran.html”{“count”:1,“id”:ObjectId(“5175a065d7f115dd41097df6 ”)}

好身份证“ http://www.nytimes.com/interactive/2013/04/22/sports/boston-moment.html”{“count”:1,“id”:ObjectId(“5175a0657c9c963654094d25 ”)}

YYYThu Jun 20 11:42:11 [conn19938] query vox.system.indexes query: { ns: "vox.tmp.mr.pi_analytics_spark_trending_inventories_6667_inc" } nreturned:1 reslen:131 0ms Thu Jun 20 11:42:11 [conn19938]查询vox.tmp.mr.pi_analytics_spark_trending_inventories_6667 nreturned:9 reslen:1716 0ms

ZZZbad id " http://www.nytimes.com/2013/04/22/business/comedy-central-to-host-comedy-festival-on-twitter.html " { "count" : 2, "first" : ISODate("2013-04-22T20:41:11Z"), "last": ObjectId("5175a067b25f029a1d092802"), "lastCounted": ObjectId("5175a067b25f029a1d092802") }

坏 id " http://www.nytimes.com/2013/04/22/business/media/in-boston-cnn-stumbles-in-rush-to-break-news.html " { "count" : 7, “第一”:ISODate(“2013-04-22T20:41:09Z”),“最后”:ObjectId(“5175a067d7f115dd41097e3c”),“lastCounted”:ObjectId(“5175a067d7f115dd41097e3c”)}

XXX - 从我的 map 函数发出的一堆记录(包含一个带有计数和 id 的值) YYY - 某种 mongo,即使我不熟悉 ZZZ - 事件发生后,reduce 被调用以前的 reduce 作业的输出...

TLDR,当我运行 map reduce 时,reduce 运行良好,直到 mongo 进程运行,然后我开始看到传递给我的 reduce 函数的先前 reduce 函数的返回值。

知道为什么/怎么可能吗?

运行 mongo 2.0.6

提前致谢

4

1 回答 1

0

我弄清楚了情况。当将 map reduce 作业的输出放入已经存在的集合中时,mongo 将通过 reduce 函数将新减少的文档和已经在输出集合中的具有相同键的文档传回。

如果您从 map 发出的值和从 reduce 返回的值具有一致的格式,则此方法可以无缝工作。

这一点都没有很好的记录,但现在我发现我的挫败感已经转化为一种聪明的感觉。惨痛的教训。未来的美好时光。

于 2013-06-20T20:35:31.157 回答