"dropDups" syntaxe pro vytváření indexu byla od verze MongoDB 2.6 „zastarána“ a v MongoDB 3.0 byla odstraněna. Ve většině případů není příliš dobrý nápad toto používat, protože „odstranění“ je libovolné a jakýkoli „duplikát“ by mohl být odstraněn. Což znamená, že to, co bude „odstraněno“, nemusí být to, co skutečně chcete odstranit.
V každém případě dochází k chybě "délka indexu", protože hodnota indexového klíče by zde byla delší, než je povoleno. Obecně řečeno, nejste „míněni“ k indexování 43 polí v žádné normální aplikaci.
Pokud chcete odstranit „duplikáty“ z kolekce, pak nejlépe uděláte, když spustíte agregační dotaz, abyste zjistili, které dokumenty obsahují „duplicitní“ data, a poté projděte tento seznam a odstraňte „všechny kromě jednoho“ již „unikátních“ _id
hodnoty z cílové kolekce. Toho lze dosáhnout pomocí „hromadných“ operací pro maximální efektivitu.
POZNÁMKA :Je pro mě těžké uvěřit, že vaše dokumenty ve skutečnosti obsahují 43 „unikátních“ polí. Je pravděpodobné, že „vše, co potřebujete“ je jednoduše identifikovat pouze pole, díky nimž je dokument „jedinečný“, a poté postupujte podle níže uvedeného postupu:
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();
Pokud máte verzi MongoDB "nižší" než 2.6 a nemáte hromadné operace, můžete to zkusit pomocí standardního .remove()
i uvnitř smyčky. Všimněte si také, že .aggregate()
nevrátí sem kurzor a opakování se musí změnit na:
db.testkdd.aggregate([
// pipeline as above
]).result.forEach(function(doc) {
doc.ids.shift();
db.testkdd.remove({ "_id": { "$in": doc.ids } });
});
Nezapomeňte si však pečlivě prohlédnout své dokumenty a zahrnout pouze „pouze“ „unikátní“ pole, u kterých očekáváte, že budou součástí seskupení _id
. Jinak nakonec neodstraníte vůbec nic, protože tam nejsou žádné duplikáty.