jeśli jesteś przygotowany na po prostu odrzucenie wszystkich innych duplikatów, zasadniczo chcesz .aggregate()
w celu pobrania dokumentów z tym samym RegisterNumber
wartość i usuń wszystkie inne dokumenty poza pierwszym dopasowaniem.
MongoDB 3.0.x brakuje niektórych nowoczesnych pomocników, ale podstaw, które .aggregate()
zwraca kursor dla dużych zestawów wyników procesu i obecności "operacji zbiorczych"
dla wydajności zapisu nadal istnieje:
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();
W bardziej nowoczesnych wydaniach ( 3.2 i nowsze ) preferowane jest użycie bulkWrite()
zamiast. Zauważ, że jest to „biblioteka klienta”, ponieważ te same metody „zbiorcze” pokazane powyżej są w rzeczywistości nazywane „pod maską”:
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);
Więc $group
ściąga wszystko razem za pomocą $RegisterNumber
wartość i zbiera pasujący dokument _id
wartości do tablicy. Liczysz, ile razy to się dzieje, używając $sum
.
Następnie odfiltruj wszystkie dokumenty, które miały tylko 1
ponieważ to wyraźnie nie są duplikaty.
Przechodząc do pętli usuwasz pierwsze wystąpienie _id
na zebranej liście dla klucza z .shift()
, pozostawiając tylko inne "duplikaty" w tablicy.
Są one przekazywane do operacji „remove” za pomocą $in
jako „lista” dokumentów do dopasowania i usunięcia.
Proces jest generalnie taki sam, jeśli potrzebujesz czegoś bardziej złożonego, takiego jak scalanie szczegółów z innych duplikatów dokumentów, po prostu możesz potrzebować większej ostrożności, jeśli robisz coś takiego jak konwersja przypadku „unikalnego klucza”, a zatem faktycznie najpierw usuwasz duplikaty przed zapisaniem zmian w dokumencie, który ma zostać zmodyfikowany.
W każdym razie agregacja wyróżni dokumenty, które faktycznie są „duplikatami”. Pozostała logika przetwarzania opiera się na tym, co faktycznie chcesz zrobić z tymi informacjami po ich zidentyfikowaniu.