MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Какъв е правилният подход за актуализиране на много записи в MongoDB с помощта на Mongoose

Подходът за изграждане на критерий, състоящ се от всички идентификационни номера на документи и след това извършване на актуализация, неизбежно ще причини потенциални проблеми. Когато итерирате списък с документи, изпращайки операция за актуализиране с всеки документ, в Mongoose рискувате да взривите сървъра си, особено когато работите с голям набор от данни, защото не чакате асинхронно извикване да завърши, преди да преминете към следващия повторение. По същество ще изграждате „стек“ от неразрешени операции, докато това не предизвика проблем - Stackoverflow.

Да вземем за пример, да предположим, че имате масив от идентификационни номера на документи, които искате да актуализирате за съответстващия документ в полето за състояние:

const processedIds = [
  "57a0a96bd1c6ef24376477cd",
  "57a052242acf5a06d4996537",
  "57a052242acf5a06d4996538"
];

където можете да използвате updateMany() метод

Model.updateMany(
  { _id: { $in: processedIds } }, 
  { $set: { status: "processed" } }, 
  callback
);

или алтернативно за наистина малки набори от данни можете да използвате forEach() метод на масива, за да го итерирате и актуализирате вашата колекция:

processedIds.forEach(function(id)){
  Model.update({ _id: id}, { $set: { status: "processed" } }, callback);
});

Горното е подходящо за малки набори от данни. Това обаче се превръща в проблем, когато се сблъскате с хиляди или милиони документи за актуализиране, тъй като ще извършвате повтарящи се сървърни извиквания на асинхронен код в рамките на цикъла.

За да преодолеете това, използвайте нещо като eachLimit<на async /код> и итерирайте масива, изпълнявайки операция за актуализиране на MongoDB за всеки елемент, като никога не извършвате повече от x паралелни актуализирания по едно и също време.

Най-добрият подход би бил да използвате груповия API за това, който е изключително ефективен при групова обработка на актуализации. Разликата в производителността спрямо извикването на операцията за актуализиране на всеки един от многото документи е, че вместо да изпраща заявките за актуализиране към сървъра с всяка итерация, масовият API изпраща заявките веднъж на всеки 1000 заявки (пакетно).

За версии на Mongoose >=4.3.0 които поддържат MongoDB сървър 3.2.x , можете да използвате bulkWrite() за актуализации. Следният пример показва как можете да направите това:

const bulkUpdateCallback = function(err, r){
  console.log(r.matchedCount);
  console.log(r.modifiedCount);
}

// Initialize the bulk operations array
const bulkUpdateOps = [], counter = 0;

processedIds.forEach(function (id) {
  bulkUpdateOps.push({
    updateOne: {
      filter: { _id: id },
      update: { $set: { status: "processed" } }
    }
  });
  counter++;

  if (counter % 500 == 0) {
    // Get the underlying collection via the Node.js driver collection object
    Model.collection.bulkWrite(bulkUpdateOps, { ordered: true, w: 1 }, bulkUpdateCallback);
    bulkUpdateOps = []; // re-initialize
  }
})

// Flush any remaining bulk ops
if (counter % 500 != 0) {
  Model.collection.bulkWrite(bulkOps, { ordered: true, w: 1 }, bulkUpdateCallback);
}

За версии на Mongoose ~3.8.8 , ~3.8.22 , 4.x които поддържат MongoDB сървър >=2.6.x , можете да използвате Bulk API както следва

var bulk = Model.collection.initializeOrderedBulkOp(),
    counter = 0;

processedIds.forEach(function(id) {
    bulk.find({ "_id": id }).updateOne({ 
        "$set": { "status": "processed" }
    });

    counter++;
    if (counter % 500 == 0) {
        bulk.execute(function(err, r) {
           // do something with the result
           bulk = Model.collection.initializeOrderedBulkOp();
           counter = 0;
        });
    }
});

// Catch any docs in the queue under or over the 500's
if (counter > 0) {
    bulk.execute(function(err,result) {
       // do something with the result here
    });
}


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Запитване на същия документ паралелно в същия API в mongoDB

  2. намалява стойността в колекцията до 0

  3. Случаи на използване за NoSQL

  4. MongoDB:Актуализиране на средна стойност в документ с 2 вложени масива

  5. Пресичане на индекса на MongoDB