私はMongoDBに非常にsimpleMap/Reduce関数を持っています。これは、コレクションからデータセットの平均を返すことを目的としています。答えがちょうど間違っていることを除いて、すべてうまくいくようです。1つのケースでは2倍です。
これが私のMap/Reduce関数です-「diff」値がどこから来ているのかを難読化する必要がありましたが、ログに返されたprintステートメントから正しいことを確認しました:
var mapFunction = function() {
if (this.fieldId==1234) {
print(diff);
}
emit(this.fieldId,diff);
};
var reduceFunction = function(keyId, viewTime) {
var count = viewTime.length;
var total = 0;
for (idx = 0; idx < viewTime.length; idx++) {
total+=viewTime[idx];
}
if (keyVidId==1234) {
print('1234: ' + total/count);
}
return total/count;
};
これを実行した後、特定のレコード1234について、MySQLから移行する前に得た結果の約2倍になり、スケーラビリティなどのためにMap/Reduceを実行することを決定する前に使用したAggregationFrameworkを使用して得た結果も2倍になります。 。他のレコードも間違っていますが、一般的にはそれほど多くはありません。
当初、reduceFunctionはArray.avgを使用していましたが、デバッグを試みるために手動平均に変換しました。
問題のデータは約23,000のドキュメントであり、各差分は非常に大きな整数になる傾向があります。
何が悪かったのかを調べてログを調べ、LibreOffice Calcを使用してログに出力された差分値を実際に手動で平均し、正しい結果を得たので、エラーはreduce関数の実装のどこかにあります。
ログに「1234:」と書かれた行が複数あることに気づきました。まるで1つのkeyIdに対してreduce関数が複数回呼び出されているかのようです。これがどのように機能しているかはわかりませんが、分割されていると思います。ワークロードを複数の関数呼び出しに分割し、最後に結合します。これは、正しい平均を取得するために結果に重みを付ける必要があることを意味します...問題がどこにあるかは想像できますが、よくわかりません。また、int32オーバーフローであることが心配でした(すべてのdiffの合計が最大値よりも大きいため)が、問題の数値をPythonで少しいじった場合はそうではないようです。
うまくいけば、誰かがMongoDBがバックグラウンドで何をしているのか、そして私が間違っているのかを明らかにすることができます...
ありがとう!