सभी दस्तावेज़ आईडी से मिलकर एक मानदंड बनाने और फिर अद्यतन करने का दृष्टिकोण संभावित मुद्दों का कारण बनता है। जब आप प्रत्येक दस्तावेज़ के साथ एक अद्यतन कार्रवाई भेजने वाले दस्तावेज़ों की एक सूची को पुनरावृत्त करते हैं, तो Mongoose में आप अपने सर्वर को उड़ाने का जोखिम उठाते हैं, विशेष रूप से बड़े डेटासेट के साथ काम करते समय क्योंकि आप अगले पर जाने से पहले एक एसिंक्रोनस कॉल के पूरा होने की प्रतीक्षा नहीं कर रहे हैं। पुनरावृत्ति आप अनिवार्य रूप से अनसुलझे कार्यों का एक "स्टैक" बना रहे होंगे जब तक कि इससे कोई समस्या न हो - स्टैक ओवरफ्लो।
उदाहरण के लिए, मान लें कि आपके पास दस्तावेज़ आईडी की एक सरणी है जिसे आप स्थिति फ़ील्ड पर मिलान करने वाले दस्तावेज़ को अपडेट करना चाहते हैं:
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);
});
उपरोक्त छोटे डेटासेट के लिए ठीक है। हालाँकि, यह एक समस्या बन जाती है जब आपको अद्यतन करने के लिए हजारों या लाखों दस्तावेज़ों का सामना करना पड़ता है क्योंकि आप लूप के भीतर एसिंक्रोनस कोड के बार-बार सर्वर कॉल कर रहे होंगे।
इस पर काबू पाने के लिए async के eachLimit<जैसी किसी चीज़ का उपयोग करें /कोड>
और प्रत्येक आइटम के लिए MongoDB अपडेट ऑपरेशन करने वाले सरणी पर पुनरावृति करें, जबकि एक ही समय में x से अधिक समानांतर अपडेट कभी नहीं करें।
इसके लिए सबसे अच्छा तरीका यह होगा कि इसके लिए बल्क एपीआई का उपयोग किया जाए जो कि बल्क में अपडेट को प्रोसेस करने में बेहद कुशल है। कई दस्तावेज़ों में से प्रत्येक पर अपडेट ऑपरेशन को कॉल करने के प्रदर्शन में अंतर यह है कि प्रत्येक पुनरावृत्ति के साथ सर्वर को अपडेट अनुरोध भेजने के बजाय, बल्क एपीआई प्रत्येक 1000 अनुरोधों (बैच) में एक बार अनुरोध भेजता है।पी>
नेवला संस्करणों के लिए >=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);
}
नेवला संस्करणों के लिए ~3.8.8.8
, ~3.8.22
, 4.x
जो MongoDB सर्वर का समर्थन करते हैं >=2.6.x
, आप बल्क एपीआई का उपयोग निम्नानुसार कर सकते हैं
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
});
}