MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Entfernen Sie Duplikate aus MongoDB

Die "dropDups" Syntax für die Indexerstellung wurde ab MongoDB 2.6 „veraltet“ und in MongoDB 3.0 entfernt. Es ist in den meisten Fällen keine sehr gute Idee, dies zu verwenden, da die "Entfernung" willkürlich ist und jedes "Duplikat" entfernt werden könnte. Was bedeutet, dass das, was "entfernt" wird, möglicherweise nicht das ist, was Sie wirklich entfernen möchten.

Wie auch immer, Sie laufen auf einen "Indexlängen" -Fehler, da der Wert des Indexschlüssels hier länger wäre als zulässig. Im Allgemeinen sind Sie in keiner normalen Anwendung "dazu bestimmt", 43 Felder zu indizieren.

Wenn Sie die „Duplikate“ aus einer Sammlung entfernen möchten, führen Sie am besten eine Aggregationsabfrage durch, um festzustellen, welche Dokumente „duplizierte“ Daten enthalten, und durchlaufen dann diese Liste, indem Sie „alle bis auf eines“ der bereits „eindeutigen“ _id Werte aus der Zielsammlung. Dies kann mit "Bulk"-Vorgängen für maximale Effizienz erfolgen.

HINWEIS :Ich finde es schwer zu glauben, dass Ihre Dokumente tatsächlich 43 "eindeutige" Felder enthalten. Es ist wahrscheinlich, dass "alles, was Sie brauchen" ist einfach nur zu identifizieren jene Felder, die das Dokument "einzigartig" machen, und folgen Sie dann dem Prozess wie unten beschrieben:

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

Wenn Sie eine MongoDB-Version „niedriger“ als 2.6 haben und keine Massenoperationen haben, können Sie es mit Standard .remove() versuchen auch innerhalb der Schleife. Beachten Sie auch, dass .aggregate() gibt hier keinen Cursor zurück und die Schleife muss sich ändern zu:

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

Sehen Sie sich Ihre Dokumente jedoch genau an und fügen Sie nur "nur" die "eindeutigen" Felder ein, von denen Sie erwarten, dass sie Teil der Gruppierung _id sind . Andernfalls entfernen Sie am Ende überhaupt nichts, da dort keine Duplikate vorhanden sind.