0

Map Reduceを使用して、日付ごとのフィールド値の1つに従ってドキュメント数をカウントしようとしています。まず、いくつかの通常のfind()関数の結果を次に示します。

db.errors.find({ "cDate" : ISODate("2012-11-20T00:00:00Z") }).count();

579を返します(つまり、この日付には579のドキュメントがあります)

db.errors.find( { $and: [ { "cDate" : ISODate("2012-11-20T00:00:00Z") }, {"Type":"General"} ] } ).count()

443を返します(つまり、Type = "General"の場合、この日付には443のドキュメントがあります)

以下は私のMapReduceです:

db.runCommand({ mapreduce: "errors", 
 map : function Map() {
    emit(
        this.cDate,//Holds a date value
        {
        count: 1,
        countGeneral: 1,
        Type: this.Type 
        }
    );
},

reduce : function Reduce(key, values) {
    var reduced = {count:0,countGeneral:0,Type:''};

    values.forEach(function(val) {
        reduced.count += val.count; 
        if (val.Type === 'General')
            reduced.countGeneral += val.countGeneral;
    });

return reduced; 
},

finalize : function Finalize(key, reduced) {
    return reduced;
},

query : { "cDate" : { "$gte" : ISODate("2012-11-20T00:00:00Z") } },

out : { inline : 1 }
});

日付20-11-20の場合、マップはリターンを減らします。

count: 579

countGeneral: 60 (should be 443 according to the above find query)

今、私は、Reduceがループする方法で予測できないことを理解しているので、これをどのように行う必要がありますか?ありがとう

4

2 に答える 2

1

削減部分で「一般」を返さないという理由だけで、残りの値を失うことをお勧めします。

mapパーツで出力され、関数から返されるすべての値に対して、Reduceが複数回実行されreduceます。

たとえば、reduceの最初の反復が実行されると、次のようなものを含む出力オブジェクトが得られます。

{count: 15, countGeneral: 3, Type: ''}

そして、reduceの他の反復は、このオブジェクトとこのような他のオブジェクトを収集し、Type:'General'そこに表示されず、それ以上増加しcountGeneralません。

于 2012-11-27T14:42:57.833 に答える
0

マップ機能が間違っています。あなたはこのようなことをすることができます:

function Map() {
    var cG=0;
    if (this.Type == 'General') { cG=1; }
    emit(
        this.cDate,//Holds a date value
        {
        count: 1,
        countGeneral: cG
        }
    );
}

これにより、Typeが「General」の場合はcountGeneral 1が発行され、それ以外の場合は0が発行されます。

次に、reduce関数でタイプチェックを破棄しているため、emit関数からタイプチェックを完全に削除できます。現在、reduce clobbers Type情報は、reduceフェーズ中にemitから渡されます。

于 2012-11-27T17:53:35.183 に答える