web-dev-qa-db-fra.com

mongo 3 duplique un index unique - dropDups

Dans la documentation de mongoDB, il est indiqué: "Modifié dans la version 3.0: l'option dropDups n'est plus disponible."

Y a-t-il quelque chose que je puisse faire (autre que le déclassement) si je veux réellement créer un index unique et détruire les entrées en double?

veuillez garder à l'esprit le fait que je reçois environ 300 insertions par seconde. Je ne peux donc pas simplement supprimer tous les doublons et espérer qu'aucun ne parviendra avant la fin de l'indexation. 

15
Alonzorz

Oui dropDupes est maintenant obsolète depuis la version 2.7.5 car il n’était pas possible de prédire correctement quel document serait supprimé au cours du processus.

En règle générale, vous avez 2 options:

  1. Utilisez une nouvelle collection:

    • Créer une nouvelle collection,
    • Créer l'index unique sur cette nouvelle collection,
    • Exécutez un lot pour copier tous les documents de l'ancienne collection dans la nouvelle et assurez-vous d'ignorer les erreurs de clé dupliquées au cours du processus.
  2. Traitez-le manuellement dans votre propre collection:

    • assurez-vous de ne pas insérer plus de documents dupliqués dans votre code,
    • lancez un lot sur votre collection pour supprimer les doublons (et assurez-vous de conserver le bon s'ils ne sont pas complètement identiques),
    • puis ajoutez l'index unique.

Pour votre cas particulier, je recommanderais le première option mais avec une astuce: 

  • Créer une nouvelle collection avec un index unique,
  • Mettez à jour votre code pour insérer maintenant des documents dans both tables,
  • Exécuter un lot pour copier tous les documents de l'ancienne collection dans la nouvelle (ignorer l'erreur de clé dupliquée),
  • renommez la nouvelle collection pour qu'elle corresponde à l'ancien nom.
  • re-mettre à jour votre code afin d'écrire maintenant uniquement dans la "vieille" collection
12
Maxime Beugnet

Comme l'a souligné @ Maxime-Beugnet, vous pouvez créer un script de traitement par lots pour supprimer les doublons d'une collection. J'ai inclus ci-dessous mon approche qui est relativement rapide si le nombre de doublons est faible par rapport à la taille de la collection. À des fins de démonstration, ce script dédoublera la collection créée par le script suivant:

db.numbers.drop()

var counter = 0
while (counter<=100000){
  db.numbers.save({"value":counter})
  db.numbers.save({"value":counter})
  if (counter % 2 ==0){
    db.numbers.save({"value":counter})
  }
  counter = counter + 1;
}

Vous pouvez supprimer les doublons de cette collection en écrivant une requête agrégée qui renvoie tous les enregistrements avec plusieurs doublons.

var cur = db.numbers.aggregate([{ $group: { _id: { value: "$value" }, uniqueIds: { $addToSet: "$_id" }, count: { $sum: 1 } } }, { $match: { count: { $gt: 1 } } }]);

À l'aide du curseur, vous pouvez ensuite parcourir les enregistrements en double et mettre en œuvre votre propre logique métier pour choisir les doublons à supprimer. Dans l'exemple ci-dessous, je garde simplement la première occurrence:

while (cur.hasNext()) {
    var doc = cur.next();
    var index = 1;
    while (index < doc.uniqueIds.length) {
        db.numbers.remove(doc.uniqueIds[index]);
        index = index + 1;
    }
}

Après la suppression des doublons, vous pouvez ajouter un index unique:

db.numbers.createIndex( {"value":1},{unique:true})
7
Jaco

pip install mongo_remove_duplicate_indexes

le meilleur moyen sera de créer un script python ou, dans la langue de votre choix, de modifier la collection, de créer une nouvelle collection avec un index unique défini sur true avec db.collectionname.createIndex ({'indexname': 1}, unique: true ) , et insérez vos documents de la collection précédente dans la nouvelle collection. Etant donné que la clé souhaitée doit être distincte ou supprimée, elle ne sera pas insérée dans votre nouvelle collection et vous pourrez gérer facilement l’écriture avec une gestion des exceptions.

consultez le code source du package pour l'exemple

0
user7106300