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 の結果は、出力のようには見えません。

4

1 に答える 1

3

問題は、配列をマッピングしていないが、reduce が配列にプッシュしようとしていることです。

各キーを「out」と「weight」のペアの配列にマップしたい場合は、それを含む配列を発行する必要があり、reduce で配列を連結する必要があります。

reduce関数によって返されるオブジェクトの構造は、map 関数が発行する値の構造と同じでなければならないことに注意してください。

つまり、マップが (キー、値) を発行するとき、「値」の構造は、reduce 関数が結果として返すものの構造と同一でなければなりません。

マップ関数をこれに変更すると、その値はフィールド「値」を持つドキュメントになります。これは、それぞれフィールド「アウト」とフィールド「重み」を持つドキュメントの配列です。

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);
    }
}

これは、上記で発行した値と同じ構造を持つように結果を構築します(キーごとに渡されたものを連結するだけなので):

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 に答える