Memperbarui banyak dokumen menggunakan array objek

Saya menggunakan server express.js. Saya mencoba memperbarui dokumen yang ada di koleksi mongodb menggunakan luwak dengan berbagai objek (setiap objek memiliki properti _id dan nilainya sesuai dengan setiap dokumen _id.)

Salah satu pendekatannya adalah mengulang array dan mengeksekusi findByIdAndUpdate()

for(var i=0; i < expenseListToEdit.length; i++) {    
    var expense = expenseListToEdit[i];

    Expense.findByIdAndUpdate(expense._id, expense, function(err, model) {
        if (err) {    
            console.log('Error occurred while editing expense');
        }

        console.log('model: ' + util.inspect(model));
    });
}

Tapi dengan cara ini saya harus menangani skenario asynchronous dan harus memeriksa kapan permintaan db untuk semua iterasi selesai kemudian hanya mengirim respons kembali ke klien dari server.

Apakah ada pendekatan alternatif dalam luwak untuk mengedit/memodifikasi array objek sekaligus dan kemudian memanggil panggilan balik?

Catatan*- Setiap objek array memiliki _id yang cocok dengan nilai dokumen _id.


person Abhijeet Srivastava    schedule 16.12.2016    source sumber


Jawaban (3)


Ya, itu sangat mungkin. Anda dapat memanfaatkan penggunaan API penulisan massal untuk menangani operasi asinkron sehingga menghasilkan kinerja yang lebih baik, terutama saat menangani kumpulan data besar. Untuk versi Mongoose >=4.3.0 yang mendukung MongoDB Server 3.2.x, Anda dapat menggunakan bulkWrite() untuk pembaruan. Contoh berikut menunjukkan bagaimana Anda dapat melakukan hal ini:

var bulkUpdateCallback = function(err, r){
    console.log(r.matchedCount);
    console.log(r.modifiedCount);
}
// Initialise the bulk operations array
var bulkOps = expenseListToEdit.map(function (expense) { 
    return { 
        "updateOne": { 
            "filter": { "_id": expense._id } ,              
            "update": { "$set": expense } 
        }         
    }    
});

// Get the underlying collection via the native node.js driver collection object
Expense.collection.bulkWrite(bulkOps, { "ordered": true, w: 1 }, bulkUpdateCallback);

Untuk versi Mongoose ~3.8.8, ~3.8.22, 4.x yang mendukung Server MongoDB >=2.6.x, Anda dapat menggunakan Bulk API sebagai berikut

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

expenseListToEdit.forEach(function(expense) {
    bulk.find({ "_id": expense._id })
        .updateOne({ "$set": expense });

    counter++;
    if (counter % 500 == 0) {
        bulk.execute(function(err, r) {
           // do something with the result
           bulk = Expense.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
    });
}
person chridam    schedule 16.12.2016

Solusinya adalah mengubah pernyataan for dengan async.each http://caolan.github.io/async/docs.html#each :

Peringatan : Masing-masing meluncurkan semua elemen secara paralel.

async.each(expenseListToEdit, function (expense, done) {
    Expense.findByIdAndUpdate(expense._id, expense, function(err, model) {
        if (err) {    
           console.log('Error occurred while editing expense');
           done(err); // if an error occured, all each is stoped
           return;
        }

        console.log('model: ' + util.inspect(model));
        done();
    });
}, function (err) {
    // final callback launched after all findByIdAndUpdate calls.
});
person throrin19    schedule 16.12.2016

person    schedule
comment
silakan coba tambahkan beberapa penjelasan tentang cara kerja kode ini dan alasannya, mungkin dengan tautan ke dokumentasi - person dheiberg; 25.07.2017