我正在准备一些有关已售公寓价格的数据,以进行回归分析。一类是房屋所在的街道,但是有些街道的面积截然不同,所以我想用建筑年份和街道名称来组合一个类别。
Broadway 1910
Broadway 2001
例如,我面临的挑战是有时建设需要跨越两年时间。数据来自瑞典,以大型集中式住房项目而闻名。我想以某种方式将这些房屋归为一个时期。这是我当前的代码。我知道这不是很有效,但是只能在一个不大的数据集上运行一次。
(async () =>{
let client;
try {
client = await MongoClient;
let collection = client.db("booliscraper").collection("sold");
let docs = await collection.find();
await docs.forEach((sale) => {
sale.street = sale.location.address.streetAddress.split(/[0-9]/)[0] + sale.location.namedAreas[0]
sale.streetYear = sale.street+" "+sale.constructionYear
log(sale);
collection.replaceOne({_id: ObjectId(sale._id)}, doc)
});
client.close();
} catch(err) {
log(err)
}
})()
答案 0 :(得分:0)
正如您正确地说的那样,当您处理大量数据集时,当前代码效率很低,因此,您可以在服务器端replaceOne
中多次调用服务器来执行forEach
,而无需聚合查询,该查询使用$ group管道计算所需的类别字段,并将属于这些类别的文档推送到一个数组中,稍后您将使用该数组进行批量更新。
对于批量更新,可以在将具有多个updateMany操作的集合上使用bulkWrite
方法。
以下操作在实践中显示了上述直觉:
(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)
}
})()