Skema Anda saat ini memiliki marks
tipe data bidang sebagai string dan Anda memerlukan tipe data integer untuk kerangka kerja agregasi Anda untuk menghitung jumlahnya. Di sisi lain, Anda dapat menggunakan MapReduce
untuk menghitung jumlah karena memungkinkan penggunaan metode JavaScript asli seperti parseInt()
pada properti objek Anda dalam fungsi petanya. Jadi secara keseluruhan Anda memiliki dua pilihan.
Opsi 1:Skema Pembaruan (Ubah Jenis Data)
Yang pertama adalah mengubah skema atau menambahkan bidang lain di dokumen Anda yang memiliki nilai numerik aktual bukan representasi string. Jika ukuran dokumen koleksi Anda relatif kecil, Anda dapat menggunakan kombinasi kursor mongodb find()
, forEach()
dan update()
metode untuk mengubah skema tanda Anda:
db.student.find({ "marks": { "$type": 2 } }).snapshot().forEach(function(doc) {
db.student.update(
{ "_id": doc._id, "marks": { "$type": 2 } },
{ "$set": { "marks": parseInt(doc.marks) } }
);
});
Untuk ukuran koleksi yang relatif besar, kinerja db Anda akan lambat dan disarankan untuk menggunakan pembaruan massal mongo untuk ini:
Versi MongoDB>=2.6 dan <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 versi 3.2 dan yang lebih baru:
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);
Opsi 2:Jalankan MapReduce
Pendekatan kedua adalah menulis ulang kueri Anda dengan MapReduce
di mana Anda dapat menggunakan fungsi JavaScript parseInt()
.
Dalam MapReduce
Anda operasi, tentukan fungsi peta yang memproses setiap dokumen input. Fungsi ini memetakan marks
. yang dikonversi nilai string ke subject
untuk setiap dokumen, dan memancarkan subject
dan mengonversi marks
pasangan. Di sinilah fungsi asli JavaScript parseInt()
dapat diaplikasikan. Catatan:dalam fungsi, this
mengacu pada dokumen yang sedang diproses oleh operasi pengurangan peta:
var mapper = function () {
var x = parseInt(this.marks);
emit(this.subject, x);
};
Selanjutnya, tentukan fungsi pengurangan yang sesuai dengan dua argumen keySubject
dan valuesMarks
. valuesMarks
adalah array yang elemennya adalah marks
bilangan bulat nilai yang dipancarkan oleh fungsi peta dan dikelompokkan berdasarkan keySubject
.Fungsi ini mengurangi valuesMarks
array ke jumlah elemennya.
var reducer = function(keySubject, valuesMarks) {
return Array.sum(valuesMarks);
};
db.student.mapReduce(
mapper,
reducer,
{
out : "example_results",
query: { subject : "maths" }
}
);
Dengan koleksi Anda, di atas akan menempatkan hasil agregasi MapReduce Anda dalam koleksi baru db.example_results
. Jadi, db.example_results.find()
akan menampilkan:
/* 0 */
{
"_id" : "maths",
"value" : 163
}