Rechercher des enregistrements en double dans MongoDB

116

Comment trouver des champs en double dans une collection mongo.

Je voudrais vérifier si l'un des champs "nom" est en double.

{
    "name" : "ksqn291",
    "__v" : 0,
    "_id" : ObjectId("540f346c3e7fc1054ffa7086"),
    "channel" : "Sales"
}

Merci beaucoup!

Chris
la source
5
L'indicateur en double pour cette question n'est pas mérité. Cette question demande comment trouver des enregistrements en double, pas pour les empêcher.
Harry King le

Réponses:

210

Utilisez l'agrégation nameet obtenez nameavec count > 1:

db.collection.aggregate(
    {"$group" : { "_id": "$name", "count": { "$sum": 1 } } },
    {"$match": {"_id" :{ "$ne" : null } , "count" : {"$gt": 1} } }, 
    {"$project": {"name" : "$_id", "_id" : 0} }
)

Pour trier les résultats du plus au moins en double:

db.collection.aggregate(
    {"$group" : { "_id": "$name", "count": { "$sum": 1 } } },
    {"$match": {"_id" :{ "$ne" : null } , "count" : {"$gt": 1} } }, 
    {"$sort": {"count" : -1} },
    {"$project": {"name" : "$_id", "_id" : 0} }     
)

Pour utiliser avec un autre nom de colonne que "nom", remplacez " $ name " par " $ column_name "

anhlc
la source
1
"$match": {"_id" :{ "$ne" : null } - n'est ici pas nécessaire, car la deuxième partie de l'instruction suffirait à filtrer le résultat. Donc, seule la vérification du groupe count > 1fera l'affaire.
BatScream
5
Tks @BatScream. {"$ ne": null} est là juste au cas où 'nom' est nul ou n'existe pas. L'agrégation comptera également nul.
anhlc
1
Bienvenue. Mais alors pourquoi vérifier le _idterrain. Il est toujours garanti qu'il n'est pas nul après l' groupopération.
BatScream
4
Le _idd'un document d'une $groupétape peut être nul.
wdberkeley
1
Quel en sera le résultat? Si je cours, j'obtiens tous les documents dont j'ai besoin, c'est que je ne veux que les identifiants / noms dupliqués.
Kannan T
24

Vous pouvez trouver listdes duplicatenoms en utilisant les éléments suivants aggregatepipeline:

  • Grouptous les enregistrements ayant des similitudes name.
  • Matchceux groupsqui ont des enregistrements supérieurs à 1.
  • Puis à groupnouveau à projecttous les noms en double sous forme de fichier array.

Le code:

db.collection.aggregate([
{$group:{"_id":"$name","name":{$first:"$name"},"count":{$sum:1}}},
{$match:{"count":{$gt:1}}},
{$project:{"name":1,"_id":0}},
{$group:{"_id":null,"duplicateNames":{$push:"$name"}}},
{$project:{"_id":0,"duplicateNames":1}}
])

o / p:

{ "duplicateNames" : [ "ksqn291", "ksqn29123213Test" ] }
BatScream
la source
10

La réponse donnée par Anhic peut être très inefficace si vous avez une grande base de données et que le nom d'attribut n'est présent que dans certains des documents.

Pour améliorer l'efficacité, vous pouvez ajouter une correspondance $ à l'agrégation.

db.collection.aggregate(
    {"$match": {"name" :{ "$ne" : null } } }, 
    {"$group" : {"_id": "$name", "count": { "$sum": 1 } } },
    {"$match": {"count" : {"$gt": 1} } }, 
    {"$project": {"name" : "$_id", "_id" : 0} }
)
Juanín
la source
3
db.getCollection('orders').aggregate([  
    {$group: { 
            _id: {name: "$name"},
            uniqueIds: {$addToSet: "$_id"},
            count: {$sum: 1}
        } 
    },
    {$match: { 
        count: {"$gt": 1}
        }
    }
])

Premier groupe Interrogez le groupe en fonction des champs.

Ensuite, nous vérifions l'identifiant unique et le comptons.Si le nombre est supérieur à 1, le champ est dupliqué dans toute la collection afin que cette chose soit gérée par la requête $ match.

Aman Shrivastava
la source
1
Je n'ai pas réussi à faire fonctionner celui-ci pour moi aussi. Vers le bas du vote!
Mathieu G
Ce message est ancien mais peut aider quelqu'un. vérifier cela, je vais vérifier dans ma section locale, cela fonctionne. Même moi, je suis tombé sur un blog à ce sujet. Jetez un coup d'oeil s'il vous plait. compose.com/articles/finding-duplicate-documents-in-mongodb
Aman shrivastava
J'ai pu le faire fonctionner - édité pour mettre à jour vers la version de travail confirmée.
AL Strine