sql >> Database >  >> NoSQL >> MongoDB

Duplicaten verwijderen uit MongoDB

De "dropDups" syntaxis voor het maken van indexen is "verouderd" vanaf MongoDB 2.6 en verwijderd in MongoDB 3.0. Het is in de meeste gevallen geen goed idee om dit te gebruiken, omdat het "verwijderen" willekeurig is en elk "duplicaat" kan worden verwijderd. Wat betekent dat wat wordt "verwijderd" misschien niet is wat je echt wilt verwijderen.

Hoe dan ook, u komt een "indexlengte"-fout tegen omdat de waarde van de indexsleutel hier langer zou zijn dan is toegestaan. Over het algemeen is het niet de bedoeling dat u 43 velden indexeert in een normale toepassing.

Als u de "duplicaten" uit een verzameling wilt verwijderen, kunt u het beste een aggregatiequery uitvoeren om te bepalen welke documenten "dubbele" gegevens bevatten en vervolgens door die lijst bladeren en "op één na" van de reeds "unieke" _id waarden uit de doelverzameling. Dit kan worden gedaan met "Bulk"-bewerkingen voor maximale efficiëntie.

OPMERKING :Ik vind het moeilijk te geloven dat uw documenten daadwerkelijk 43 "unieke" velden bevatten. Het is waarschijnlijk dat "alles wat je nodig hebt" is om eenvoudig alleen . te identificeren die velden die het document "uniek" maken en volg dan het proces zoals hieronder beschreven:

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

Als je een MongoDB-versie "lager" dan 2.6 hebt en geen bulkbewerkingen hebt, kun je het proberen met standaard .remove() ook binnen de lus. Merk ook op dat .aggregate() zal hier geen cursor retourneren en de looping moet veranderen in:

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

Maar zorg ervoor dat u uw documenten goed bekijkt en alleen "alleen" de "unieke" velden opneemt waarvan u verwacht dat ze deel uitmaken van de groepering _id . Anders verwijder je uiteindelijk helemaal niets, omdat er geen duplicaten zijn.




  1. Hoe te controleren of socket in leven is (verbonden) in socket.io met meerdere knooppunten en socket.io-redis

  2. Trek een item uit een array via Meteor

  3. Azure Function met Cosmos MongoDB-integratie wordt niet opgeslagen

  4. Hoe zorg je voor een uniek item in een array op basis van specifieke velden - mongoDB?