ако сте готови просто да изхвърлите всички други дубликати, тогава всъщност искате да .aggregate()
за да съберете документите със същия RegisterNumber
стойност и премахнете всички други документи, различни от първото съвпадение.
На MongoDB 3.0.x липсват някои от съвременните помощници, но основите, които .aggregate()
връща курсор за големи набори от резултати на процеса и наличието на "групови операции"
за производителност при запис все още съществува:
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();
В по-модерни версии (3.2 и по-нови) се предпочита да се използва bulkWrite()
вместо. Имайте предвид, че това е нещо от „клиентска библиотека“, тъй като същите „групови“ методи, показани по-горе, всъщност се наричат „под капака“:
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);
Така че $group
събира всичко заедно чрез $RegisterNumber
стойност и събира съответстващия документ _id
стойности към масив. Вие поддържате броя на това колко пъти се случва това, като използвате $sum
.
След това филтрирайте всички документи, които имат само брой 1
тъй като очевидно не са дубликати.
Преминавайки към цикъла, премахвате първото срещане на _id
в събрания списък за ключа с .shift()
, оставяйки само други „дубликати“ в масива.
Те се предават на операцията „премахване“ с $inкод>
като „списък“ с документи за съпоставяне и премахване.
Процесът като цяло е същият, ако имате нужда от нещо по-сложно, като например обединяване на детайли от други дублиращи се документи, просто може да се нуждаете от повече внимание, ако правите нещо като преобразуване на регистъра на „уникалния ключ“ и следователно действително първо премахване на дубликатите преди да напишете промени в документа, който ще бъде модифициран.
Във всеки случай агрегирането ще подчертае документите, които всъщност са „дубликати“. Останалата логика на обработка се основава на това, което всъщност искате да направите с тази информация, след като ги идентифицирате.