Reputation: 7739
I have a collection with the following document
{
"_id" : 1,
"item" : "item1",
"stock" : 184
}
{
"_id" : 2,
"item" : "item2",
"stock" : 330
}
{
"_id" : 3,
"item" : "item3",
"stock" : 140
}
I want to update this collection like this using a single query.
{
"_id" : 1,
"item" : "item1",
"stock" : 80
}
{
"_id" : 2,
"item" : "item2",
"stock" : 60
}
{
"_id" : 3,
"item" : "item3",
"stock" : 170
}
I can do it using forEach
but I have to update thousands of records at once which will time consuming. So does MongoDB have this functionality?
Your help will be highly appreciated.
Upvotes: 3
Views: 2490
Reputation: 46441
Even more concise way
Array you want to update with
const array = [{
"_id" : 1,
"item" : "item1",
"stock" : 80
}, {
"_id" : 2,
"item" : "item2",
"stock" : 60
}, {
"_id" : 3,
"item" : "item3",
"stock" : 170
}]
Query to for bulk update
Model.bulkWrite(
array.map((data) =>
({
updateOne: {
filter: { _id: data._id },
update: { $set: { stock: data.stock } }
}
})
)
})
Upvotes: 1
Reputation: 59882
You can use a bulk operation in nodejs via Collection.initializeUnorderedBulkOp
var bulkOp = yourCollection.initializeUnorderedBulkOp();
bulkOp.find({ _id: 1 }).updateOne({ /* update document */ });
bulkOp.find({ _id: 2 }).updateOne({ /* update document */ });
// etc
bulkOp.execute();
You can build it however you need to and then have the database do it all at once.
Upvotes: 6
Reputation: 23495
You can't perform the changes you want using a single request.
What you can do is :
Having small amount of data
Launch one request for each change to perform
await Promise.all(entries.map(x => model.findOneAndUpdate(...)));
Having a large amount of data
Use cursor to handle the data by packs.
const cursor = await model.find({
_id: {
$in: idsEntries,
},
}).cursor().exec();
await handleCursorRead(cursor);
handleCursorRead(cursor) {
return new Promise((resolve) => {
cursor.eachAsync((x) => {
x.stock = ...;
x.save();
}, {
// How many items do we look at same time
parallel: 250,
}, () => {
// When we are done processing all items
resolve();
});
});
}
Upvotes: 2