sql >> Databáze >  >> NoSQL >> MongoDB

Odstraňte duplikáty z MongoDB

"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.




  1. MongoDB $ cos

  2. Jak aktualizovat hodnotu pole v Mongoose

  3. Jak StackExchange.Redis používá více koncových bodů a připojení?

  4. Časový limit provádění SET {Key}, inst:0, mgr:Neaktivní, fronta:2, qu=1, qs=1, qc=0, wr=1/1, in=0/0