これは正しい方法で行っていますが、 .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)
}
}
);
}
})
したがって、 position $
効果を発揮する演算子。
とにかくループで生成しているので、表記に「インデックス」値を使用することもできます。
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
);
}
})
これは、一致するインデックスを使用するだけで、配列要素の一意の識別子がない場合に便利です。
また、既存のドキュメントの処理方法の性質上、ここでは「アップサート」または「マルチ」オプションのどちらも適用しないことに注意してください。
これに対する「追記」のメモと同様に、2.6以降のバージョンのMongoDBのBulkOperationsAPIを検討することも価値があります。これらのAPIメソッドを使用すると、クライアントアプリケーションとデータベース間のネットワークトラフィックの量を大幅に減らすことができます。ここでの明らかな改善は、全体的な速度にあります:
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();
これにより、基本的に、サーバーに送信される操作ステートメントの量が、キューに入れられた1000回の操作ごとに1回だけ送信されるようになります。その数とグループ化の方法で遊ぶことができますが、比較的安全な方法で速度が大幅に向上します。