4

map/reduceの動作を理解しようとしています。

マップ関数は次のとおりです。

function() {
  var klass = this.error_class;
  emit('klass', { model : klass, count : 1 });
}

そしてreduce機能:

function(key, values) {
  var results = { count : 0, klass: { foo: 'bar' } };
  values.forEach(function(value) {
    results.count += value.count;
    results.klass[value.model] = 0;
    printjson(results);
  });
  return results;
}

それから私はそれを実行します:

{
  "count" : 85,
  "klass" : {
    "foo" : "bar",
    "Twitter::Error::BadRequest" : 0
  }
}
{
  "count" : 86,
  "klass" : {
    "foo" : "bar",
    "Twitter::Error::BadRequest" : 0,
    "Stream:DirectMessage" : 0
  }
}

この時点では、すべてが良好ですが、100ドキュメントごとに読み取りロックが生成されます。

{
  "count" : 100,
  "klass" : {
    "foo" : "bar",
    "Twitter::Error::BadRequest" : 0,
    "Stream:DirectMessage" : 0
  }
}
{ "count" : 100, "klass" : { "foo" : "bar", "undefined" : 0 } }

キーを保持fooし、count属性を増やし続けました。問題は、他のすべてがになったことですundefined

countでは、属性がまだ良好であるのに、なぜオブジェクトの動的キーが失われるのでしょうか。

4

1 に答える 1

0

reduce関数について覚えておくべきことは、reduce関数に渡される値は、map関数の出力か、reduceへの以前の呼び出しの戻り値のいずれかであるということです。

これは重要です。つまり、データの一部のマッピング/削減をさまざまなマシン(たとえば、mongoクラスターのさまざまなシャード)にファームオフしてから、データを再構築するために再度使用することができます。また、mongoは最初にすべての値をマップし、すべての結果をメモリに保持してからすべてを減らす必要がないことも意味します。つまり、マップしてチャンクに減らし、必要に応じて再削減することができます。

言い換えれば、次のことが当てはまる必要があります。

reduce(k,[A,B,C]) == reduce(k, [A,  reduce(k,[A,B]))

reduce関数の出力にはmodelプロパティがないため、re-reduceで使用されると、これらの未定義の値が発生します。

区別せずに2つを処理できるように(通常は最も簡単)、reduce関数にマップ関数が出力するものと同じ形式の何かを返すようにするか、再縮小された値を異なる方法で処理する必要があります。

于 2012-09-21T17:29:46.437 に答える