mongodb mapreduce不会在分片群集中返回

时间:2014-04-25 04:47:59

标签: mongodb collections mapreduce sharding

非常有趣,mapreduce在单个实例中工作正常,但不在分片集合中工作。如下所示,您可能会看到我收集了一个简单的map-reduce 功能,

mongos> db.tweets.findOne()
{
    "_id" : ObjectId("5359771dbfe1a02a8cf1c906"),
    "geometry" : {
        "type" : "Point",
        "coordinates" : [
            131.71778292855996,
            0.21856835860911106
        ]
    },
    "type" : "Feature",
    "properties" : {
        "isflu" : 1,
        "cell_id" : 60079,
        "user_id" : 35,
        "time" : ISODate("2014-04-24T15:42:05.048Z")
    }
}
mongos> db.tweets.find({"properties.user_id":35}).count()
44247
mongos> map_flow
function () { var key=this.properties.user_id; var value={ "cell_id":1}; emit(key,value); }
mongos> reduce2
function (key,values){ var ros={flows:[]}; values.forEach(function(v){ros.flows.push(v.cell_id);});return ros;}
mongos> db.tweets.mapReduce(map_flow,reduce2, { out:"flows2", sort:{"properties.user_id":1,"properties.time":1} })

但结果不是我想要的

mongos> db.flows2.find({"_id":35})
{ "_id" : 35, "value" : { "flows" : [  null,  null,  null ] } }

我有很多空,有趣的都有三个。 mongodb mapreduce似乎不适合分片收集?

1 个答案:

答案 0 :(得分:1)

MapReduce的首要规则是:

  • 您将发出与reduce function returneth相同类型的值

你破坏了这个规则,所以你的MapReduce只适用于小集合,其中reduce只对每个键调用一次(这是MapReduce的第二个规则 - reduce函数可以被称为零,一次或多次)。

您的地图功能会为每个文档准确发出此值{cell_id:1}

你的reduce函数如何使用这个值?好吧,您返回一个值,该值是一个带有数组的文档,您可以在其中推送cell_id值。这已经很奇了,因为那个值是1,所以我不确定为什么你不会只发出1(如果你想数)。

但是看看当多个分片将一堆1推入这个流数组时会发生什么(无论它是你想要的,这就是你的代码正在做的事情),现在还会在几个已经减少的值上调用:

reduce(key, [ {flows:[1,1,1,1]},{flows:[1,1,1,1,1,1,1,1,1]}, etc ] )

您的reduce函数现在尝试获取values数组的每个成员(这是一个包含单个字段flows的文档)并将v.cell_id推送到您的流数组。这里没有cell_id字段,所以当然你最终会得到null。三个空值可能是因为你有三个分片?

我建议你清楚地告诉自己你在这段代码中想要聚合的是什么,然后重写你的map和你的reduce以符合MongoDB中mapReduce希望你的代码遵循的规则。