„dropDups” składnia do tworzenia indeksów została „przestarzała” w MongoDB 2.6 i usunięta w MongoDB 3.0. W większości przypadków używanie tego nie jest dobrym pomysłem, ponieważ „usunięcie” jest arbitralne i każdy „duplikat” może zostać usunięty. Co oznacza, że to, co zostanie „usunięte”, może nie być tym, co naprawdę chcesz usunąć.
W każdym razie napotykasz błąd „długości indeksu”, ponieważ wartość klucza indeksu byłaby dłuższa niż dozwolona. Ogólnie rzecz biorąc, nie masz indeksować 43 pól w żadnej normalnej aplikacji.
Jeśli chcesz usunąć „duplikaty” z kolekcji, najlepszym rozwiązaniem jest uruchomienie zapytania agregującego w celu określenia, które dokumenty zawierają „zduplikowane” dane, a następnie przechodzenie przez tę listę, usuwając „wszystkie oprócz jednego” z już „unikalnych” _id
wartości z kolekcji docelowej. Można to zrobić za pomocą operacji zbiorczych, aby uzyskać maksymalną wydajność.
UWAGA :Trudno mi uwierzyć, że twoje dokumenty faktycznie zawierają 43 "unikalne" pola. Prawdopodobnie „wszystko, czego potrzebujesz” jest po prostu zidentyfikować tylko te pola, które sprawiają, że dokument jest „unikatowy”, a następnie postępuj zgodnie z procesem opisanym poniżej:
var bulk = db.testkdd.initializeOrderedBulkOp(),
count = 0;
// List "all" fields that make a document "unique" in the `_id`
// I am only listing some for example purposes to follow
db.testkdd.aggregate([
{ "$group": {
"_id": {
"duration" : "$duration",
"protocol_type": "$protocol_type",
"service": "$service",
"flag": "$flag"
},
"ids": { "$push": "$_id" },
"count": { "$sum": 1 }
}},
{ "$match": { "count": { "$gt": 1 } } }
],{ "allowDiskUse": true}).forEach(function(doc) {
doc.ids.shift(); // remove first match
bulk.find({ "_id": { "$in": doc.ids } }).remove(); // removes all $in list
count++;
// Execute 1 in 1000 and re-init
if ( count % 1000 == 0 ) {
bulk.execute();
bulk = db.testkdd.initializeOrderedBulkOp();
}
});
if ( count % 1000 != 0 )
bulk.execute();
Jeśli masz wersję MongoDB „niższą” niż 2.6 i nie masz operacji zbiorczych, możesz spróbować ze standardowym .remove()
wewnątrz pętli. Zauważając również, że .aggregate()
nie zwróci tutaj kursora, a pętla musi zmienić się na:
db.testkdd.aggregate([
// pipeline as above
]).result.forEach(function(doc) {
doc.ids.shift();
db.testkdd.remove({ "_id": { "$in": doc.ids } });
});
Ale pamiętaj, aby dokładnie przyjrzeć się swoim dokumentom i uwzględnić tylko „tylko” „unikalne” pola, które mają być częścią grupowania _id
. W przeciwnym razie niczego nie usuniesz, ponieważ nie ma tam duplikatów.