不明白为什么/如何使用地图减少



我正在尝试使用map reduce来了解什么时候这会有所帮助。

所以我有一个名为"动作"的集合,里面有10万个这样的文档:

{
    "profile_id":1111,
    "action_id":2222
}

现在我正在尝试做map reduce示例。我正在尝试获得"所有用户和每个用户的总操作"的列表。这可能吗?我的代码:

db.fbooklikes.mapReduce(
    function(){
        emit(this.profile_id, this.action_id);
    },
    function(keyProfile, valueAction){
        return Array.sum(valueAction);
    },
    {
        out:"example"
    }
)

这不起作用。结果是:

"counts" : {
    "input" : 100000,
    "emit" : 100000,
    "reduce" : 1146,
    "output" : 13
},
"ok" : 1,
"_o" : {
    "result" : "map_reduce_example",
    "timeMillis" : 2539,
    "counts" : {
        "input" : 100000,
        "emit" : 100000,
        "reduce" : 1146,
        "output" : 13
    },
    "ok" : 1
},

我想用map reduce做点什么?

是的,你可以使用它,但更精细的回应是,可能有更好的工具来做你想做的事情。

MapReduce对于某些任务很方便,但通常最适合在其他任务不适用时使用。在MongoDB中包含mapReduce早于聚合框架的引入,这通常是您应该在可能的时候使用的:

db.fbooklikes.aggregate([
    { "$group": {
        "_id": "$profile_id",
        "count": { "$sum": 1 }
    }}
])

它将简单地返回集合中所有文档的计数,这些文档按"profile_id"的每个值分组。

MapReduce需要JavaScript评估,因此运行速度比聚合框架实现的本地代码函数慢得多。有时你必须使用它,但在简单的情况下,最好不要使用,而且你需要了解一些怪癖:

db.fbooklikes.mapReduce(
    function(){
        emit(this.profile_id, 1);
    },
    function(key,values){
        return Array.sum(values);
    },
    {
        out: { "inline": 1 }
    }
)

人们对mapReduce最怀念的一点是,每个发出的键几乎从未调用过reducer一次。事实上,它将以"块"的形式处理输出,从而"减少"该输出的一部分,并将其放回以相对于其他输出再次"减少",直到该键只有一个值为止。

因此,重要的是从reduce函数发出与从"map"函数发送的数据类型相同的数据。当你不理解函数的这一部分时,这是一个棘手的问题,可能会导致奇怪的结果。事实上,这是mapReduce处理单个键值的大值结果并减少它们的基本方式。

但一般来说,您应该在可能的情况下使用聚合框架,如果问题需要一些特殊的计算,而这些计算在那里是不可能的,或者有一些复杂的文档遍历,需要使用JavaScript进行检查,那么这就是您使用mapReduce的地方。

您不想对操作ID求和,而是想对它们进行计数。所以你想要像下面这样的

var map = function () {
    emit(this.profile_id, { action_ids : [this.action_id], count : 1  });
}
var reduce  = function(profile_id, values) {
    var value = { action_ids: [], count: 0 };
    for (var i = 0; i < values.length; i++) {
        value.count += values[i].count;
        value.action_ids.push.apply(value.action_ids, values[i].action_ids);
    }
    return value;
}
db.fbooklikes.mapReduce(map, reduce, { out:"example" });

这将为您提供一个操作id数组和每个配置文件id的计数。该计数可以通过访问action_ids数组的length来获得,但我想我会将其分开以使示例更清晰。

最新更新