Robisz to we właściwy sposób, ale nie uwzględniłeś elementu tablicy do dopasowania w części zapytania .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)
}
}
);
}
})
Musisz więc dopasować coś w tablicy, aby pozycyjny $
operatora, aby mieć jakikolwiek efekt.
Mogłeś również użyć wartości „indeks” w notacji, ponieważ i tak tworzysz ją w pętli:
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
);
}
})
Który po prostu używa pasującego indeksu i jest przydatny, gdy nie ma unikalnego identyfikatora elementu tablicy.
Należy również pamiętać, że ani opcje „upsert” ani „multi” nie powinny mieć tutaj zastosowania ze względu na sposób przetwarzania istniejących dokumentów.
Tak jak „postscript” do tego, warto również rozważyć Bulk Operations API MongoDB w wersjach od 2.6 i nowszych. Korzystając z tych metod interfejsu API, można znacznie zmniejszyć ruch sieciowy między aplikacją kliencką a bazą danych. Oczywista poprawa dotyczy ogólnej szybkości:
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();
Zasadniczo zmniejsza to liczbę wyciągów operacji wysyłanych do serwera do wysyłania tylko raz na 1000 operacji w kolejce. Możesz bawić się tą liczbą i sposobem grupowania rzeczy, ale zapewni to znaczny wzrost prędkości w stosunkowo bezpieczny sposób.