MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Como alterar o tipo de dados do campo aninhado no documento Mongo?


Você está fazendo isso da maneira correta, mas não incluiu o elemento array para corresponder na parte da consulta do .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)
             }
         }
      );
  }
})

Então você precisa combinar algo na matriz para que o posicional $ operador tenha algum efeito.

Você também poderia ter usado o valor "index" na notação, já que você está produzindo isso em um loop de qualquer maneira:
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 apenas usa o índice correspondente e é útil onde não há identificador exclusivo do elemento da matriz.

Observe também que nem as opções "upsert" ou "multi" devem ser aplicadas aqui devido à natureza de como isso processa os documentos existentes.

Assim como uma nota "postscript" para isso, também vale a pena considerar a API de operações em massa do MongoDB nas versões 2.6 e superiores. Usando esses métodos de API, você pode reduzir significativamente a quantidade de tráfego de rede entre seu aplicativo cliente e o banco de dados. A melhoria óbvia aqui está na velocidade geral:
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();

Isso basicamente reduz a quantidade de instruções de operações enviadas ao servidor para enviar apenas uma vez a cada 1.000 operações enfileiradas. Você pode brincar com esse número e como as coisas são agrupadas, mas isso dará um aumento significativo na velocidade de uma maneira relativamente segura.