0

我正在尝试在 mongodb 中使用 mapreduce 运行 pagerank。

我的文件是这种格式:

{
        "_id" : "u: 10000",
        "value" : [
                [
                        "u: 10000",
                        "s: 985272",
                        1
                ],
                [
                        "s: 985272",
                        "u: 10000",
                        1
                ],
                [
                        "u: 10000",
                        "s: 303770",
                        1
                ],
                [
                        "s: 303770",
                        "u: 10000",
                        1
                ]
        ]
}

现在我认为第一步是按键收集链接。但是,我每个文档有几个出站链接。(这些都是双向的)。

这是我的 map 和 reduce 函数:

m = function () {
    for (var i = 0; i < this.value.length; i++){
        var out = {};
        out.out = this.value[i][1];
        out.weight = this.value[i][2];
        emit(this.value[i][0], [out]);
    }
}

r = function(key, values){
    var result = {
      value: [] 
    };
    values.forEach(function(val) {
    result.value.push({out: val.out, weight: val.weight});
    });
    return result;
}

问题是我不确定 emit 是否会为每个文档产生多个排放。当我得到如下结果时:

{
        "_id" : "s: 1000082",
        "value" : [
                {
                        "out" : "u: 37317",
                        "weight" : 1
                }
        ]
}

当我期望每个文档有多个项目时。

有人有想法么?帮助将不胜感激!

编辑:

我并不完全满意,例如这样的事情是如何工作的?reduce 结果看起来一点也不像 emit 输出。

4

1 回答 1

3

问题是您没有映射数组,但您的 reduce 试图推送到数组。

如果你想让每个键映射到一个“out”和“weight”对的数组,那么你需要发出一个包含它的数组,并且在你的reduce中你需要将数组连接在一起。

请记住,reduce 函数返回的对象的结构必须与 map 函数发出的值的结构相同。

这意味着当您的地图发出 (key, value) 时,“值”的结构必须与您的 reduce 函数返回的结构相同。

如果您将 map 函数更改为此,则该值是一个带有字段“value”的文档,它是一个文档数组,每个文档都有字段“out”和字段“weight”:

function () {
    for (var i = 0; i < this.value.length; i++) {
        key = this.value[i][0];
        value = {value:[{out:this.value[i][1], weight:this.value[i][2]}]};
        emit(key, value);
    }
}

和你的reduce函数,它构造结果与你在上面发出的值具有相同的结构(因为它只是连接它为每个键传入的内容):

function (key, values) {
    result = {value:[]};
    for (var i in values) {
        result.value = values[i].value.concat(result.value);
    }
    return result;
}

然后你会得到你所期望的。

{
    "_id" : "s: 303770",
    "value" : {
        "value" : [
            {
                "out" : "u: 10000",
                "weight" : 1
            }
        ]
    }
}
{
    "_id" : "s: 985272",
    "value" : {
        "value" : [
            {
                "out" : "u: 10000",
                "weight" : 1
            }
        ]
    }
}
{
    "_id" : "u: 10000",
    "value" : {
        "value" : [
            {
                "out" : "s: 303770",
                "weight" : 1
            },
            {
                "out" : "s: 985272",
                "weight" : 1
            }
        ]
    }
}
于 2012-07-01T23:00:51.307 回答