sql >> Base de Datos >  >> NoSQL >> MongoDB

¿Cómo cambiar el tipo de datos del campo anidado en el documento Mongo?

Está haciendo esto de la manera correcta, pero no incluyó el elemento de matriz para que coincida en la parte de consulta de .update() :

db.collectionName.find({
   "topProcesses":{"$exists":true}}).forEach(function(data){
    for(var ii=0;ii<data.topProcesses.length;ii++) {
      db.collectionName.update(
         { 
             "_id": data._id, 
             "topProcesses.processId": data.topProcesses[ii].processId // corrected
         },
         {
             "$set": {
               "topProcesses.$.cpuUtilizationPercent":
                   parseFloat(data.topProcesses[ii].cpuUtilizationPercent)
             }
         }
      );
  }
})

Por lo tanto, debe hacer coincidir algo en la matriz para que el posicional $ operador tenga algún efecto.

También podría haber usado el valor "índice" en la notación, ya que de todos modos lo está produciendo en un bucle:

db.collectionName.find({
   "topProcesses":{"$exists":true}}).forEach(function(data){
    for(var ii=0;ii<data.topProcesses.length;ii++) {

      var updoc =  { 
          "$set": {}
      };

      var myKey = "topProcesses." + ii + ".cpuUtilizationPercent";
      updoc["$set"][myKey] = parseFloat(data.topProcesses[ii].cpuUtilizationPercent);

      db.collectionName.update(
         { 
             "_id": data._id
         },
         updoc
      );
  }
})

Que solo usa el índice coincidente y es útil cuando no hay un identificador único del elemento de la matriz.

También tenga en cuenta que ni las opciones "upsert" ni "multi" deben aplicarse aquí debido a la naturaleza de cómo se procesan los documentos existentes.

Solo como una nota de "posdata" a esto, también vale la pena considerar la API de operaciones masivas de MongoDB en versiones de 2.6 y posteriores. Con estos métodos API, puede reducir significativamente la cantidad de tráfico de red entre su aplicación cliente y la base de datos. La mejora obvia aquí está en la velocidad general:

var bulk = db.collectionName.initializeOrderedBulkOp();
var counter = 0;

db.collectionName.find({
   "topProcesses":{"$exists":true}}
).forEach(function(data){
    for(var ii=0;ii<data.topProcesses.length;ii++) {

      var updoc =  { 
          "$set": {}
      };

      var myKey = "topProcesses." + ii + ".cpuUtilizationPercent";
      updoc["$set"][myKey] = parseFloat(data.topProcesses[ii].cpuUtilizationPercent);

      // queue the update
      bulk.find({ "_id": data._id }).update(updoc);
      counter++;

      // Drain and re-initialize every 1000 update statements
      if ( counter % 1000 == 0 ) {
          bulk.execute();
          bulk = db.collectionName.initializeOrderedBulkOp();
      }
  }
})

// Add the rest in the queue
if ( counter % 1000 != 0 )
    bulk.execute();

Básicamente, esto reduce la cantidad de declaraciones de operaciones enviadas al servidor a solo enviar una vez cada 1000 operaciones en cola. Puedes jugar con ese número y cómo se agrupan las cosas, pero te dará un aumento significativo en la velocidad de una manera relativamente segura.