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.