7

MongoDB では、特定の基準を満たす場合にのみデータを保存する Map-Reduce 関数を作成しようとしています。

レデューサーからemit()しない方法がわかりません。何らかの方法で常にデータを保存します。

一般的な例を次に示します。データのコンテキストは無視してください。このデータとコードは、この質問のためだけに作成しました。

データセット:

{ "_id" : ObjectId("52583b3a58da9769dda48853"), "date" : "01-01-2013", "count" : 1 }
{ "_id" : ObjectId("52583b3d58da9769dda48854"), "date" : "01-01-2013", "count" : 1 }
{ "_id" : ObjectId("52583b4258da9769dda48855"), "date" : "01-02-2013", "count" : 1 }
{ "_id" : ObjectId("52583b4f58da9769dda48856"), "date" : "01-03-2013", "count" : 4 }

マップ機能:

// Map all data by (date, count)
var map = function() {
    var key = this.date;
    var value = this.count;
    emit(key, value);
}

不要なデータを単純に無視するリデューサー。

// Only save dates which have count > 2
var reducer = function(date, counts) {
    var sum = Array.sum(counts);
    if (sum > 2) {
        return sum;
    }
}

結果 (値 1 は無視されませんでした):

{ "_id" : "01-01-2013", "value" : null }
{ "_id" : "01-02-2013", "value" : 1 }
{ "_id" : "01-03-2013", "value" : 4 }

空の return ステートメントも追加しましたが、同じ結果が得られました。

// Only save dates which have count > 2
var reducer = function(date, counts) {
    var sum = Array.sum(counts);
    if (sum > 2) {
        return sum;
    }
    else return;
}

私が望んでいるのは、Map-Reduce を実行した後、出力コレクションに次のデータのみが存在することです。どうすればこれを達成できますか?

{ "_id" : "01-03-2013", "value" : 4 }
4

2 に答える 2

3

次の関数を使用して、追加の mapReduce 操作を実行できます。

var second_map = function() { 
    if(this.value > 2) {
        emit(this._id, this.value);
    }
}

var second_reduce = function() {}

キーごとに複数の値がないと、この場合は呼び出されないため、reduce 関数は空にすることができます。

したがって、次のように mapReduce を実行します。

db.map_reduce_example.mapReduce(
    second_map, second_reduce, {out: 'final_mapreduce_result'});

次のコレクションが生成されます。

> db.final_mapreduce_result.find()
{ "_id" : "01-03-2013", "value" : 4 }

if (sum > 2)このアプローチを使用する場合は、最初の reduce 関数から条件を削除できることに注意してください。

于 2013-10-15T08:37:46.590 に答える
2

キーに対して( map() から)発行された値が1つしかない場合、レデューサーをスキップできることを覚えておく必要があります。また、reduce は同じキーに対して複数回呼び出される可能性があるため (毎回、出力された値のサブセットを使用して)、reduce で結果をフィルター処理しようとしないでください。

他の唯一のオプションは finalize メソッドですが、結果からエントリが削除されるのではなく、null 値になります。

必要な結果を得る唯一の方法は、map reduce の代わりに集計フレームワークを使用することだと思います。パイプラインは次のようになります。

db.test.aggregate( 
   { 
     "$project" : { 
       "_id"   : 0, 
       "date"  : 1, 
       "count" : 1 
     } 
   }, 
   { 
     "$group" : { 
       "_id"   : "$date", 
       "value" : { "$sum" : "$count" } 
     } 
   }, 
   { 
     "$match" : { 
       "value" : { "$gt" : 2 } 
     } 
   } 
);
{ "result" : [ { "_id" : "01-03-2013", "value" : 4 } ], "ok" : 1 }

このアプローチの唯一の大きな欠点は、結果をインラインで返す必要があるため、結果のサイズが 16MB に制限されることです。これは 2.6 リリースで修正/修正される予定です: https://jira.mongodb.org/browse/SERVER-10097

HTH、ロブ。

于 2013-10-15T01:25:17.220 に答える