Estoy usando un script para eliminar duplicados en mongo, se trabajó en una colección con 10 elementos que he usado como una prueba, pero cuando he usado para la colección real con 6 millones de documentos, me sale un error.

Este es el script que me encontré en Robomongo (ahora conocido como Robo 3T):

var bulk = db.getCollection('RAW_COLLECTION').initializeOrderedBulkOp();
var count = 0;

db.getCollection('RAW_COLLECTION').aggregate([
  //Group on unique value storing _id values to array and count 
  { "$group": {
    "_id": { RegisterNumber: "$RegisterNumber", Region: "$Region" },
    "ids": { "$push": "$_id" },
    "count": { "$sum": 1 }      
  }},
  //Only return things that matched more than once. i.e a duplicate
  { "$match": { "count": { "$gt": 1 } } }
]).forEach(function(doc) {
  var keep = doc.ids.shift();     //takes the first _id from the array

  bulk.find({ "_id": { "$in": doc.ids }}).remove(); //remove all remaining _id matches
  count++;

  if ( count % 500 == 0 ) {  //only actually write per 500 operations
      bulk.execute();
      bulk = db.getCollection('RAW_COLLECTION').initializeOrderedBulkOp();  //re-init after execute
  }
});

//Clear any queued operations
if ( count % 500 != 0 )
    bulk.execute();

Este es el mensaje de error:

Error: command failed: {
    "errmsg" : "exception: Exceeded memory limit for $group, but didn't allow external sort. Pass allowDiskUse:true to opt in.",
    "code" : 16945,
    "ok" : 0
} : aggregate failed :
[email protected]/mongo/shell/utils.js:23:13
[email protected]/mongo/shell/assert.js:13:14
assert.[email protected]/mongo/shell/assert.js:266:5
DBCollection.prototype.[email protected]/mongo/shell/collection.js:1215:5
@(shell):1:1

Así que tengo que configurar allowDiskUse:true a trabajar? ¿Dónde puedo hacer que en el script y no hay ningún problema en hacer esto?

InformationsquelleAutor kadzu | 2017-05-24

3 Comentarios

  1. 39
    { allowDiskUse: true } 

    Debe ser colocado justo después de la agregación de la tubería.

    En que este código debe ir así:

    db.getCollection('RAW_COLLECTION').aggregate([
      //Group on unique value storing _id values to array and count 
      { "$group": {
        "_id": { RegisterNumber: "$RegisterNumber", Region: "$Region" },
        "ids": { "$push": "$_id" },
        "count": { "$sum": 1 }      
      }},
      //Only return things that matched more than once. i.e a duplicate
      { "$match": { "count": { "$gt": 1 } } }
    ], { allowDiskUse: true } )
    • Pero es seguro, para establecer la verdadera? Yo no entiendo por qué esto es necesario
    • La agregación de canalización de etapas uso máximo de memoria límite. Para manejar grandes conjuntos de datos, conjunto de allowDiskUse opción a true para habilitar la escritura de datos a archivos temporales. Esto debería darle una variación de rendimiento en comparación con cuando se lee por completo de la memoria. También dependerá del tamaño del conjunto de datos
  2. 0

    De MongoDB Docs

    El $de la fase de grupos tiene un límite de 100 megabytes de RAM. Por defecto, si
    la etapa supera este límite, $grupo, se producirá un error. Sin embargo,
    para permitir la manipulación de grandes conjuntos de datos, establezca la allowDiskUse
    opción a true para habilitar $operaciones del grupo para escribir temporal
    los archivos. Ver db.de la colección.aggregate() método y el conjunto de comandos
    para obtener más detalles.

  3. 0

    Siempre es mejor usar partido antes de que el grupo cuando se tienen datos de gran tamaño.
    Si usted está usando partido antes de grupo, usted no conseguirá en este problema.

    db.getCollection('sample').aggregate([
       {$match:{State:'TAMIL NADU'}},
       {$group:{
           _id:{DiseCode:"$code", State:"$State"},
           totalCount:{$sum:1}
       }},
    
       {
         $project:{
            Code:"$_id.code",
            totalCount:"$totalCount",
            _id:0 
         }   
    
       }
    
    ])

    Si realmente superar este problema sin partido, entonces la solución es { allowDiskUse: true }

Dejar respuesta

Please enter your comment!
Please enter your name here