tutorial indexes index dropdups compound mongodb optimization duplicates key

dropdups - mongodb indexes tutorial



¿Cómo eliminar duplicados basados en una clave en Mongodb? (7)

Tengo una colección en MongoDB donde hay alrededor (~ 3 millones de registros). Mi registro de muestra se vería así,

{ "_id" = ObjectId("50731xxxxxxxxxxxxxxxxxxxx"), "source_references" : [ "_id" : ObjectId("5045xxxxxxxxxxxxxx"), "name" : "xxx", "key" : 123 ] }

Tengo muchos registros duplicados en la colección que tienen el mismo source_references.key . (Por duplicado quiero decir, source_references.key no el _id ).

Quiero eliminar registros duplicados basados ​​en source_references.key , estoy pensando en escribir un código PHP para atravesar cada registro y eliminar el registro si existe.

¿Hay alguna manera de eliminar los duplicados en la línea de comando interna de Mongo?


Aquí hay una forma un poco más ''manual'' de hacerlo:

Básicamente, primero, obtenga una lista de todas las claves únicas que le interesan.

Luego realice una búsqueda con cada una de esas teclas y elimine si esa búsqueda devuelve más de una.

db.collection.distinct("key").forEach((num)=>{ var i = 0; db.collection.find({key: num}).forEach((doc)=>{ if (i) db.collection.remove({key: num}, { justOne: true }) i++ }) });


Eliminar duplicados por marco de agregación .

a. Si quieres eliminar de una vez.

var duplicates = []; db.collectionName.aggregate([ // discard selection criteria, You can remove "$match" section if you want { $match: { source_references.key: { "$ne": '''' } }}, { $group: { _id: { source_references.key: "$source_references.key"}, // can be grouped on multiple properties dups: { "$addToSet": "$_id" }, count: { "$sum": 1 } }}, { $match: { count: { "$gt": 1 } // Duplicates considered as count greater than one }} ]) // You can display result until this and check duplicates .forEach(function(doc) { doc.dups.shift(); // First element skipped for deleting doc.dups.forEach( function(dupId){ duplicates.push(dupId); // Getting all duplicate ids } ) }) // If you want to Check all "_id" which you are deleting else print statement not needed printjson(duplicates); // Remove all duplicates in one go db.collectionName.remove({_id:{$in:duplicates}})

segundo. Puede borrar documentos uno por uno.

db.collectionName.aggregate([ // discard selection criteria, You can remove "$match" section if you want { $match: { source_references.key: { "$ne": '''' } }}, { $group: { _id: { source_references.key: "$source_references.key"}, // can be grouped on multiple properties dups: { "$addToSet": "$_id" }, count: { "$sum": 1 } }}, { $match: { count: { "$gt": 1 } // Duplicates considered as count greater than one }} ]) // You can display result until this and check duplicates .forEach(function(doc) { doc.dups.shift(); // First element skipped for deleting db.collectionName.remove({_id : {$in: doc.dups }}); // Delete remaining duplicates })


Esta es la consulta más fácil que utilicé en mi MongoDB 3.2

db.myCollection.find({}, {myCustomKey:1}).sort({_id:1}).forEach(function(doc){ db.myCollection.remove({_id:{$gt:doc._id}, myCustomKey:doc.myCustomKey}); })

customKey su customKey antes de ejecutar esto para aumentar la velocidad


Mientras que @Stennie''s es una respuesta válida, no es la única. De hecho, el manual MongoDB le pide que sea muy cauteloso al hacer eso. Hay otras dos opciones

  1. Deje que el MongoDB lo haga por usted usando Map Reduce
  2. Lo haces programatically que es menos eficiente.

Si está seguro de que source_references.key identifica registros duplicados, puede garantizar un índice único con las dropDups:true opción de creación de índice dropDups:true en MongoDB 2.6 o una dropDups:true anterior:

db.things.ensureIndex({''source_references.key'' : 1}, {unique : true, dropDups : true})

Esto mantendrá el primer documento único para cada valor de source_references.key , y descartará cualquier documento subsiguiente que de otro modo causaría una violación duplicada de la clave.

Notas importantes :

  • La opción dropDups fue eliminada en MongoDB 3.0 , por lo que se requerirá un enfoque diferente. Por ejemplo, puede usar la agregación como se sugiere en: documentos duplicados MongoDB incluso después de agregar una clave única .
  • Cualquier documento que no source_references.key campo source_references.key se considerará que tiene un valor nulo , por lo que los documentos subsiguientes que no tengan el campo clave se eliminarán. Puede agregar la opción de creación de índice source_references.key sparse:true para que el índice solo se aplique a los documentos con un campo source_references.key .

Precaución obvia : Realice una copia de seguridad de su base de datos y pruebe esto en un entorno de prueba primero si le preocupa la pérdida de datos involuntarios.


Si tienes suficiente memoria, en scala puedes hacer algo como eso:

cole.find().groupBy(_.customField).filter(_._2.size>1).map(_._2.tail).flatten.map(_.id) .foreach(x=>cole.remove({id $eq x})


pip instala mongo_remove_duplicate_indexes

  1. crea una secuencia de comandos en cualquier idioma
  2. iterar sobre su colección
  3. crear una nueva colección y crear un nuevo índice en esta colección con un conjunto único en verdadero, recuerde que este índice tiene que ser el mismo que el índice. Quite eliminar los duplicados de su colección original con el mismo nombre para que ex-u tenga una colección de juegos, y en este colección u tiene un género de campo que contiene duplicados, que desea eliminar, así que simplemente cree una nueva colección db.createCollection ("cname") cree un nuevo índice db.cname.createIndex ({''género'': 1}, único: 1) ahora cuando insertes un documento con un género similar, solo primero se aceptará, el otro será rechazado con un error de clave de duplicado
  4. ahora solo inserte los valores de formato json que recibió en la colección nueva y maneje la excepción usando el manejo de excepciones para ex pymongo.errors.DuplicateKeyError

consulte el código fuente del paquete para mongo_remove_duplicate_indexes para una mejor comprensión