Есть еще один способ сделать это;используйте исходный массив объектов вместо документов Mongoose с bulkWrite
.
bulkWrite
позволяет отправлять несколько insertOne
, updateOne
, updateMany
, replaceOne
, deleteOne
и / или deleteMany
операций на сервере MongoDB в одной команде вместо текущей настройки, когда вы отправляете несколько команд на сервер с циклом for.В этом случае вам потребуется несколько updateOne
операций с операцией обновления как $setOnInsert
.
Takeнапример, предположим, что у вас есть массив
const products = [
{
imagePath: '../client/src/Components/Layout/Media/armadillo.png',
title: 'Pangolin',
description: "This is a pangolin",
price: 15000
},
{
imagePath: '../client/src/Components/Layout/Media/croc.png',
title: 'Cuban corcodile',
description: "This is a croc",
price: 15000
},
{
imagePath: '../client/src/Components/Layout/Media/monkey.png',
title: 'Golden Gibbon',
description: "This is a monkey",
price: 15000
}
];
Вы можете настроить список операций updateOne
, который может иметь следующую форму
[
{ updateOne :
{
"filter" : <document>,
"update" : <document>,
"upsert" : <boolean>
}
}
]
Сопоставьте массив продуктов с вышеуказанным как
const ops = products.map(product => (
{ "updateOne": {
"filter": { "title": product.title },
"update": { "$setOnInsert": product },
"upsert": true
} }
))
. Затем можно применить bulkWrite()
к вышеуказанному как:
Product.bulkWrite(ops).then(result => console.log(result))
В приведенном выше примере, если соответствующий документ существует, обновление с $setOnInsert
ничего не делает, так как операция обновления не приводит к вставке, найдя документсоответствует запросу.
Если вы идете с исходной реализацией, вам нужно исправить запрос и затем создать обещания в цикле for следующим образом:
let promises = [];
for (let i = 0; i < products.length; i++) {
const productPromise = Product.findOne({
title: products[i].title // <- fixed
}).then(product => {
if (!product) { // <-- fixed
return products[i].save();
}
});
promises.push(productPromise);
}
Promise.all(promises).then(result => console.log(result));