sql >> Databasteknik >  >> NoSQL >> MongoDB

Ta bort dubbletter från MongoDB

"dropDups" syntax för att skapa index har "fasat ut" från och med MongoDB 2.6 och tagits bort i MongoDB 3.0. Det är inte en bra idé i de flesta fall att använda detta eftersom "borttagningen" är godtycklig och alla "dubbletter" kan tas bort. Vilket betyder att det som "tas bort" kanske inte är det du verkligen vill ta bort.

Hur som helst, du stöter på ett "indexlängd"-fel eftersom värdet på indexnyckeln här skulle vara längre än tillåtet. Generellt sett är du inte "menad" att indexera 43 fält i någon normal applikation.

Om du vill ta bort "dubbletter" från en samling är det bästa alternativet att köra en aggregeringsfråga för att avgöra vilka dokument som innehåller "dubbletter" data och sedan gå igenom listan och ta bort "alla utom en" av de redan "unika" _id värden från målsamlingen. Detta kan göras med "Bulk"-operationer för maximal effektivitet.

OBS :Jag har svårt att tro att dina dokument faktiskt innehåller 43 "unika" fält. Det är troligt att "allt du behöver" är att helt enkelt identifiera endast de fält som gör dokumentet "unikt" och följ sedan processen som beskrivs nedan:

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();

Om du har en MongoDB-version "lägre" än 2.6 och inte har bulkoperationer kan du prova med standard .remove() inuti slingan också. Notera också att .aggregate() kommer inte att returnera en markör här och loopingen måste ändras till:

db.testkdd.aggregate([
   // pipeline as above
]).result.forEach(function(doc) {
    doc.ids.shift();  
    db.testkdd.remove({ "_id": { "$in": doc.ids } });
});

Men se till att titta på dina dokument noggrant och inkludera bara "bara" de "unika" fält som du förväntar dig ska vara en del av grupperingen _id . Annars tar du inte bort någonting alls, eftersom det inte finns några dubbletter där.




  1. Ändra inställning av TTL på hSet Keys

  2. Vilken NoSQL-databas ska jag använda för loggning?

  3. db.collection är inte en funktion när du använder MongoClient v3.0

  4. ConnectionMultiplexer.Anslutning avbryts vid anslutning till redis-server