sql >> Database teknologi >  >> NoSQL >> MongoDB

Fjern dubletter fra MongoDB

"dropDups" syntaks til indeksoprettelse er blevet "udfaset" fra og med MongoDB 2.6 og fjernet i MongoDB 3.0. Det er i de fleste tilfælde ikke en særlig god idé at bruge dette, da "fjernelsen" er vilkårlig, og enhver "duplikat" kan fjernes. Hvilket betyder, at det, der bliver "fjernet", måske ikke er det, du virkelig vil have fjernet.

Under alle omstændigheder løber du ind i en "indekslængde"-fejl, da værdien af ​​indeksnøglen her ville være længere end tilladt. Generelt set er det ikke "ment" at du skal indeksere 43 felter i nogen normal applikation.

Hvis du vil fjerne "duplikaterne" fra en samling, så er dit bedste bud at køre en aggregeringsforespørgsel for at bestemme, hvilke dokumenter der indeholder "duplikatdata" og derefter cykle gennem listen og fjerne "alle undtagen én" af de allerede "unikke" _id værdier fra målsamlingen. Dette kan gøres med "Bulk"-operationer for maksimal effektivitet.

BEMÆRK :Jeg har svært ved at tro, at dine dokumenter faktisk indeholder 43 "unikke" felter. Det er sandsynligt, at "alt hvad du behøver" er simpelthen at identificere kun de felter, der gør dokumentet "unikt", og følg derefter processen som beskrevet nedenfor:

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

Hvis du har en MongoDB-version "lavere" end 2.6 og ikke har bulk-operationer, kan du prøve med standard .remove() også inde i løkken. Bemærk også, at .aggregate() returnerer ikke en markør her, og loopingen skal ændres til:

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

Men sørg for at se dine dokumenter nøje og kun inkludere "kun" de "unikke" felter, som du forventer skal være en del af grupperingen _id . Ellers ender du med at fjerne ingenting, da der ikke er nogen dubletter der.




  1. Redis værdiopdatering

  2. Redis Keyspace-meddelelser med flushdb

  3. Redis Async API'er

  4. Mongoose indlejret forespørgsel på Model efter felt i dens refererede model