3

レコードが次の形式で出力される mapreduce 関数を作成しました

{userid:<xyz>, {event:adduser, count:1}}
{userid:<xyz>, {event:login, count:1}}
{userid:<xyz>, {event:login, count:1}}
{userid:<abc>, {event:adduser, count:1}}

ここで、userid はキーで、残りはそのキーの値です。MapReduce 関数の後、次の形式で結果を取得したい

{userid:<xyz>,{events: [{adduser:1},{login:2}], allEventCount:3}}

これを達成するために、次のreduce関数を書きました。これはgroup byによって達成できることを知っています..集約フレームワークとmapreduceの両方で、複雑なシナリオでは同様の機能が必要です. だから、私はこのアプローチをとっています。

var reducefn = function(key,values){
var result = {allEventCount:0, events:[]};
values.forEach(function(value){
    var notfound=true;
    for(var n = 0; n < result.events.length; n++){
        eventObj = result.events[n];
        for(ev in eventObj){
            if(ev==value.event){
                result.events[n][ev] += value.allEventCount;
                notfound=false;
                break;
            }
        }
    }
    if(notfound==true){ 
        var newEvent={}
        newEvent[value.event]=1; 
        result.events.push(newEvent);
    }
    result.allEventCount += value.allEventCount;
});
return result;

}

これは完全に実行されます.1000レコードに対して実行すると、3kまたは10kレコードがある場合、得られる結果は次のようになります

{ "_id" : {...}, "value" :{"allEventCount" :30, "events" :[ { "undefined" : 1},
{"adduser" : 1 }, {"remove" : 3 }, {"training" : 1 }, {"adminlogin" : 1 }, 
{"downgrade" : 2 } ]} }

これがどこから来たのかを理解できずundefined、個々のイベントの合計も allEventCount 未満です。コレクション内のすべてのドキュメントには空でないフィールドeventがあるため、未定義になる可能性はありません。

Mongo DB バージョン -- 2.2.1 環境 -- ローカル マシン、シャーディングなし。

result.events[n][ev] += value.allEventCount;reduce 関数で、同様の操作が成功したときにこの操作が失敗するのはなぜresult.allEventCount += value.allEventCount;ですか?

johnyHKによって提案された正しい答え

縮小機能:

    var reducefn = function(key,values){
    var result = {totEvents:0, event:[]};
    values.forEach(function(value){
        value.event.forEach(function(eventElem){
            var notfound=true;
            for(var n = 0; n < result.event.length; n++){
                eventObj = result.event[n];
                for(ev in eventObj){
                for(evv in eventElem){
                    if(ev==evv){
                        result.event[n][ev] += eventElem[evv];
                        notfound=false;
                        break;
                    }
                }}
            }
            if(notfound==true){ 
                result.event.push(eventElem);
            }
        });
        result.totEvents += value.totEvents;
    });
    return result;
}
4

1 に答える 1

2

emit関数から取得するオブジェクトの形状は、map関数から返されるオブジェクトと同じである必要があります。これは、(この場合のように) 多数のドキュメントを処理するときreduceに a の結果がreduceフィードバックされる可能性があるためです。reduce

emitしたがって、次のようにドキュメントを発行するように変更する必要があります。

{userid:<xyz>, {events:[{adduser: 1}], allEventCount:1}}
{userid:<xyz>, {events:[{login: 1}], allEventCount:1}}

reduceそれに応じて関数を更新します。

于 2013-01-03T14:39:23.057 に答える