jika Anda siap untuk membuang semua duplikat lainnya, maka pada dasarnya Anda ingin .aggregate()
untuk mengumpulkan dokumen dengan RegisterNumber
yang sama nilai dan hapus semua dokumen lain selain kecocokan pertama.
MongoDB 3.0.x tidak memiliki beberapa pembantu modern tetapi dasar-dasar yang .aggregate()
mengembalikan kursor untuk proses kumpulan hasil besar dan adanya "operasi massal"
untuk performa tulis masih ada:
var bulk = db.collection.initializeOrderedBulkOp();
var count = 0;
db.collection.aggregate([
// Group on unique value storing _id values to array and count
{ "$group": {
"_id": "$RegisterNumber",
"ids": { "$push": "$_id" },
"count": { "$sum": 1 }
}},
// Only return things that matched more than once. i.e a duplicate
{ "$match": { "count": { "$gt": 1 } } }
]).forEach(function(doc) {
var keep = doc.ids.shift(); // takes the first _id from the array
bulk.find({ "_id": { "$in": doc.ids }}).remove(); // remove all remaining _id matches
count++;
if ( count % 500 == 0 ) { // only actually write per 500 operations
bulk.execute();
bulk = db.collection.initializeOrderedBulkOp(); // re-init after execute
}
});
// Clear any queued operations
if ( count % 500 != 0 )
bulk.execute();
Dalam rilis yang lebih modern ( 3.2 ke atas ) lebih disukai menggunakan bulkWrite()
alih-alih. Perhatikan bahwa ini adalah hal 'perpustakaan klien', karena metode "massal" yang sama yang ditunjukkan di atas sebenarnya disebut "di bawah tenda":
var ops = [];
db.collection.aggregate([
{ "$group": {
"_id": "$RegisterNumber",
"ids": { "$push": "$id" },
"count": { "$sum": 1 }
}},
{ "$match": { "count": { "$gt": 1 } } }
]).forEach( doc => {
var keep = doc.ids.shift();
ops = [
...ops,
{
"deleteMany": { "filter": { "_id": { "$in": doc.ids } } }
}
];
if (ops.length >= 500) {
db.collection.bulkWrite(ops);
ops = [];
}
});
if (ops.length > 0)
db.collection.bulkWrite(ops);
Jadi $group
menarik semuanya bersama-sama melalui $RegisterNumber
nilai dan mengumpulkan dokumen yang cocok _id
nilai ke array. Anda menghitung berapa kali ini terjadi menggunakan $sum
.
Kemudian saring semua dokumen yang hanya memiliki hitungan 1
karena itu jelas bukan duplikat.
Melewati loop Anda menghapus kemunculan pertama _id
dalam daftar yang dikumpulkan untuk kunci dengan .shift()
, hanya menyisakan "duplikat" lainnya dalam larik.
Ini diteruskan ke operasi "hapus" dengan $in
sebagai "daftar" dokumen untuk dicocokkan dan dihapus.
Prosesnya umumnya sama jika Anda memerlukan sesuatu yang lebih kompleks seperti menggabungkan detail dari dokumen duplikat lainnya, hanya saja Anda mungkin perlu lebih berhati-hati jika melakukan sesuatu seperti mengonversi kasus "kunci unik" dan karena itu benar-benar menghapus duplikat terlebih dahulu sebelum menulis perubahan pada dokumen yang akan dimodifikasi.
Bagaimanapun, agregasi akan menyoroti dokumen yang sebenarnya adalah "duplikat". Logika pemrosesan yang tersisa didasarkan pada apa pun yang sebenarnya ingin Anda lakukan dengan informasi tersebut setelah Anda mengidentifikasinya.