Du gör detta på rätt sätt men du inkluderade inte arrayelementet för att matcha i frågedelen av .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)
}
}
);
}
})
Så du måste matcha något i arrayen för att positionella
Du kunde också bara ha använt "index"-värdet i notationen, eftersom du ändå producerar det i en loop:
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
);
}
})
Som bara använder det matchande indexet och är praktiskt där det inte finns någon unik identifierare för arrayelementet.
Observera också att varken alternativen "upsert" eller "multi" bör gälla här på grund av hur detta behandlar befintliga dokument.
Precis som en "efterskrift"-notering till detta är det också värt att överväga Bulk Operations API för MongoDB i versioner från 2.6 och senare. Genom att använda dessa API-metoder kan du avsevärt minska mängden nätverkstrafik mellan din klientapplikation och databasen. Den uppenbara förbättringen här är den totala hastigheten:
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();
Detta minskar i princip mängden operationsuttalanden som skickas till servern till att bara skickas en gång var 1000:e köade operation. Du kan spela med det numret och hur saker är grupperade men det kommer att ge en avsevärd ökning av hastigheten på ett relativt säkert sätt.