Как вы правильно сказали, ваш текущий код неэффективен, когда речь идет о работе с огромными наборами данных, поэтому вместо нескольких обращений к серверу для выполнения replaceOne
в цикле forEach
вы можете создать агрегированный запрос, который вычисляет поля категорий, которые вы хотите с помощью конвейера $ group, и поместите документы, попадающие в эти категории, в массив, который вы позже будете использовать для массового обновления.
Для массового обновления вы можете использовать метод bulkWrite
для коллекции, которая будет иметь несколько операций updateMany.
Следующая операция показывает приведенную выше интуицию на практике:
(async () => {
try {
let client = await MongoClient;
let collection = client.db("booliscraper").collection("sold");
let pipeline = [
{ '$group': {
'_id': {
'street': {
'$concat': [
{
'$arrayElemAt': [
{ '$split': [
'$location.address.streetAddress',
/[0-9]/
] },
0
]
},
{ '$arrayElemAt': [ '$location.namedAreas', 0 ] },
]
},
'streetYear': { '$concat': ['$street', ' ', '$constructionYear'] }
},
'ids': { '$push': '$_id' }
} }
]
let docs = await collection.aggregate(pipeline);
let ops = docs.map(({ _id, ids }) => ({
'updateMany': {
'filter': { '_id': { '$in': ids } },
'update': { '$set': {
'street': _id.street, 'streetYear': _id.streetYear
} }
}
}));
let result = await collection.bulkWrite(ops);
log(result)
client.close()
} catch(err) {
log(err)
}
})()