MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Wie ändere ich den Datentyp eines verschachtelten Felds in einem Mongo-Dokument?

Sie machen dies richtig, aber Sie haben das Array-Element, das übereinstimmen soll, nicht in den Abfrageteil von .update() aufgenommen :

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

Sie müssen also etwas im Array abgleichen, damit der Positions-$ Operator keine Auswirkung haben.

Sie hätten auch einfach den "Index"-Wert in der Notation verwenden können, da Sie das sowieso in einer Schleife erzeugen:

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

Was nur den passenden Index verwendet und praktisch ist, wenn es keine eindeutige Kennung des Array-Elements gibt.

Beachten Sie auch, dass hier aufgrund der Art und Weise, wie vorhandene Dokumente verarbeitet werden, weder die Optionen „Upsert“ noch „Multi“ gelten sollten.

Nur als "Nachsatz"-Anmerkung dazu lohnt es sich auch, die Bulk Operations API von MongoDB in Versionen ab 2.6 und höher zu betrachten. Mit diesen API-Methoden können Sie den Netzwerkverkehr zwischen Ihrer Clientanwendung und der Datenbank erheblich reduzieren. Die offensichtliche Verbesserung liegt hier in der Gesamtgeschwindigkeit:

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

Dies reduziert im Grunde die Menge der an den Server gesendeten Operationsanweisungen auf nur einmal alle 1000 Operationen in der Warteschlange. Sie können mit dieser Anzahl spielen und wie die Dinge gruppiert werden, aber es wird auf relativ sichere Weise eine erhebliche Geschwindigkeitssteigerung geben.