Encuentra registros duplicados en MongoDB

116

¿Cómo encontraría campos duplicados en una colección de mongo?

Me gustaría comprobar si alguno de los campos de "nombre" está duplicado.

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

¡Muchas gracias!

Chris
fuente
5
La bandera duplicada para esta pregunta es inmerecida. Esta pregunta pregunta cómo encontrar registros duplicados, no cómo prevenirlos.
Harry King

Respuestas:

209

Utilice la agregación en namey obtener namecon count > 1:

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

Para ordenar los resultados de más a menos duplicados:

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

Para usar con otro nombre de columna que no sea "nombre", cambie " $ nombre " a " $ nombre_columna "

anhlc
fuente
1
"$match": {"_id" :{ "$ne" : null } - es innecesario aquí, ya que la segunda parte del enunciado bastaría con filtrar el resultado. Así que solo count > 1es suficiente comprobar si el grupo tiene .
BatScream
5
Tks @BatScream. {"$ ne": null} está ahí en caso de que 'nombre' sea nulo o no exista. La agregación también contará como nula.
anhlc
1
Bienvenidos. Pero entonces, ¿por qué comprobar el _idcampo? Siempre se garantiza que no sea nulo después de la groupoperación.
BatScream
4
El _idde un documento de una $groupetapa puede ser nulo.
wdberkeley
1
¿Cuál será el resultado de esto? Si corro, obtengo todos los documentos, lo que necesito es solo las identificaciones / nombres duplicados.
Kannan T
24

Usted puede encontrar el listde duplicatenombres usando la siguiente aggregatetubería:

  • Grouptodos los registros que tienen similares name.
  • Matchlos que groupstienen registros superiores a 1.
  • Luego de groupnuevo a projecttodos los nombres duplicados como un array.

El código:

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
fuente
10

La respuesta que dio anhic puede ser muy ineficaz si tiene una base de datos grande y el nombre del atributo está presente solo en algunos de los documentos.

Para mejorar la eficiencia, puede agregar $ match a la agregación.

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

Primer grupo Consultar el grupo según los campos.

Luego verificamos el Id único y lo contamos, si el recuento es mayor que 1, entonces el campo está duplicado en toda la colección, por lo que la consulta $ match debe manejarlo.

Aman shrivastava
fuente
1
No he podido hacer que este funcione para mí también. ¡Votación negativa!
Mathieu G
Esta publicación es antigua pero puede ayudar a alguien. Mira esto. Verificaré en mi local si está funcionando. Incluso me encontré con un blog sobre esto. Por favor échale un vistazo. compose.com/articles/finding-duplicate-documents-in-mongodb
Aman shrivastava
Pude hacer que funcionara: editado para actualizar a la versión de trabajo confirmada.
AL Strine