Lo stai facendo nel modo giusto ma non hai incluso l'elemento dell'array da abbinare nella parte della query di .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)
}
}
);
}
})
Quindi è necessario abbinare qualcosa nell'array in modo che posizionale $
operatore per avere alcun effetto.
Avresti anche potuto semplicemente usare il valore "index" nella notazione, dal momento che lo stai comunque producendo in un ciclo:
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
);
}
})
Che utilizza solo l'indice di corrispondenza ed è utile dove non esiste un identificatore univoco dell'elemento dell'array.
Tieni inoltre presente che in questo caso non dovrebbero essere applicate né le opzioni "upsert" né "multi", a causa della natura del modo in cui vengono elaborati i documenti esistenti.
Proprio come una nota "postscript" a questo, vale anche la pena considerare l'API Bulk Operations di MongoDB nelle versioni dalla 2.6 in poi. Utilizzando questi metodi API è possibile ridurre significativamente la quantità di traffico di rete tra l'applicazione client e il database. L'evidente miglioramento qui è nella velocità complessiva:
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();
Ciò riduce sostanzialmente la quantità di istruzioni delle operazioni inviate al server per l'invio solo una volta ogni 1000 operazioni in coda. Puoi giocare con quel numero e come sono raggruppate le cose, ma darà un aumento significativo della velocità in un modo relativamente sicuro.