MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Comment changer le type de données du champ imbriqué dans le document Mongo ?

Vous faites cela de la bonne manière mais vous n'avez pas inclus l'élément de tableau à faire correspondre dans la partie requête du .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)
             }
         }
      );
  }
})

Vous devez donc faire correspondre quelque chose dans le tableau afin que le positionnel $ opérateur pour avoir un effet.

Vous auriez également pu simplement utiliser la valeur "index" dans la notation, puisque vous produisez cela dans une boucle de toute façon :

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
      );
  }
})

Qui utilise simplement l'index correspondant et est pratique lorsqu'il n'y a pas d'identifiant unique de l'élément de tableau.

Notez également que ni les options "upsert" ou "multi" ne doivent s'appliquer ici en raison de la nature de la façon dont cela traite les documents existants.

En tant que note "post-scriptum", il convient également de considérer l'API Bulk Operations de MongoDB dans les versions 2.6 et supérieures. À l'aide de ces méthodes d'API, vous pouvez réduire considérablement la quantité de trafic réseau entre votre application cliente et la base de données. L'amélioration évidente ici est dans la vitesse globale :

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();

Cela réduit fondamentalement le nombre d'instructions d'opérations envoyées au serveur pour n'envoyer qu'une fois toutes les 1000 opérations en file d'attente. Vous pouvez jouer avec ce nombre et la façon dont les choses sont regroupées, mais cela augmentera considérablement la vitesse de manière relativement sûre.