現在のスキーマにはmarks
があります 文字列としてのフィールドデータ型。合計を計算するには、集計フレームワークに整数データ型が必要です。一方、MapReduce
を使用できます。 parseInt()
などのネイティブJavaScriptメソッドを使用できるため、合計を計算します マップ関数のオブジェクトプロパティ。したがって、全体として2つの選択肢があります。
オプション1:スキーマの更新(データ型の変更)
1つ目は、スキーマを変更するか、文字列表現ではなく実際の数値を持つ別のフィールドをドキュメントに追加することです。コレクションドキュメントのサイズが比較的小さい場合は、mongodbのカーソルを組み合わせて使用できます find()
、 forEach()
およびupdate()
マークスキーマを変更する方法:
db.student.find({ "marks": { "$type": 2 } }).snapshot().forEach(function(doc) {
db.student.update(
{ "_id": doc._id, "marks": { "$type": 2 } },
{ "$set": { "marks": parseInt(doc.marks) } }
);
});
コレクションサイズが比較的大きい場合、dbのパフォーマンスは遅くなるため、mongoの一括更新 このために:
MongoDBバージョン>=2.6および<3.2:
var bulk = db.student.initializeUnorderedBulkOp(),
counter = 0;
db.student.find({"marks": {"$exists": true, "$type": 2 }}).forEach(function (doc) {
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "marks": parseInt(doc.marks) }
});
counter++;
if (counter % 1000 === 0) {
// Execute per 1000 operations
bulk.execute();
// re-initialize every 1000 update statements
bulk = db.student.initializeUnorderedBulkOp();
}
})
// Clean up remaining operations in queue
if (counter % 1000 !== 0) bulk.execute();
MongoDBバージョン3.2以降:
var ops = [],
cursor = db.student.find({"marks": {"$exists": true, "$type": 2 }});
cursor.forEach(function (doc) {
ops.push({
"updateOne": {
"filter": { "_id": doc._id } ,
"update": { "$set": { "marks": parseInt(doc.marks) } }
}
});
if (ops.length === 1000) {
db.student.bulkWrite(ops);
ops = [];
}
});
if (ops.length > 0) db.student.bulkWrite(ops);
オプション2:MapReduceを実行する
2番目のアプローチは、MapReduce
を使用してクエリを書き直すことです。 ここで、JavaScript関数parseInt()
を使用できます 。
MapReduce
操作では、各入力ドキュメントを処理するマップ関数を定義します。この関数は、変換されたmarks
をマップします subject
への文字列値 ドキュメントごとに、subject
を発行します 変換されたmarks
ペア。ここで、JavaScriptネイティブ関数parseInt()
適用することができます。注:関数では、this
map-reduce操作が処理しているドキュメントを参照します:
var mapper = function () {
var x = parseInt(this.marks);
emit(this.subject, x);
};
次に、2つの引数keySubject
を使用して対応するreduce関数を定義します。 およびvaluesMarks
。 valuesMarks
要素が整数のmarks
である配列です。 map関数によって発行され、keySubject
によってグループ化された値 。この関数はvaluesMarks
を減らします 要素の合計に配列します。
var reducer = function(keySubject, valuesMarks) {
return Array.sum(valuesMarks);
};
db.student.mapReduce(
mapper,
reducer,
{
out : "example_results",
query: { subject : "maths" }
}
);
コレクションを使用すると、上記でMapReduce集計結果が新しいコレクションdb.example_results
に配置されます。 。したがって、db.example_results.find()
出力されます:
/* 0 */
{
"_id" : "maths",
"value" : 163
}