【发布时间】:2018-07-28 21:14:03
【问题描述】:
我有一个定期运行的函数,它更新我的Prices 集合中的一些Documents 的item.price。 Price Collection 有 100k+ 项。函数如下所示:
//Just a helper function for multiple GET requests with request.
let _request = (urls, cb) => {
let results = {}, i = urls.length, c = 0;
handler = (err, response, body) => {
let url = response.request.uri.href;
results[url] = { err, response, body };
if (++c === urls.length) {
cb(results);
}
};
while (i--) {
request(urls[i], handler);
}
};
// function to update the prices in our Prices collection.
const update = (cb) => {
Price.remove({}, (err, remove) => {
if (err) {
return logger.error(`Error removing items...`);
}
logger.info(`Removed all items... Beginning to update.`);
_request(urls, (responses) => {
let url, response, gameid;
for (url in responses) {
id = url.split('/')[5].split('?')[0];
response = responses[url];
if (response.err) {
logger.error(`Error in request to ${url}: ${err}`);
return;
}
if (response.body) {
logger.info(`Request to ${url} successful.`)
let jsonResult = {};
try {
jsonResult = JSON.parse(response.body);
} catch (e) {
logger.error(`Could not parse.`);
}
logger.info(`Response body for ${id} is ${Object.keys(jsonResult).length}.`);
let allItemsArray = Object.keys(jsonResult).map((key, index) => {
return {
itemid: id,
hash_name: key,
price: jsonResult[key]
}
});
Price.insertMany(allItemsArray).then(docs => {
logger.info(`Saved docs for ${id}`)
}, (e) => {
logger.error(`Error saving docs.`);
});
}
}
if (cb && typeof cb == 'function') {
cb();
}
})
});
}
如您所见,为了避免遍历 100k+ 文档并分别更新每一个文档,我在开始时将它们全部删除,然后调用为我提供这些项目的 API 和价格,并使用 @987654328 @ 将它们全部插入我的价格集合中。
此更新过程每 30 分钟发生一次。
但我现在才意识到,如果某些用户想要查看价格,而我的 Prices Collection 目前是空的,因为它正在自我更新,该怎么办?
问题
那么我是否必须遍历所有这些才能不删除它? (请记住,有很多文档每 30 分钟更新一次。)或者还有其他解决方案吗?
这是我的Prices Collection 外观的图片(有 100k 此类文档,我只想更新价格属性):
更新:
我已经稍微重写了我的update 函数,现在它看起来像这样:
const update = (cb = null) => {
Price.remove({}, (err, remove) => {
if (err) {
return logger.error(`Error removing items...`);
}
logger.info(`Removed all items... Beginning to update.`);
_request(urls, (responses) => {
let url, response, gameid;
for (url in responses) {
gameid = url.split('/')[5].split('?')[0];
response = responses[url];
if (response.err) {
logger.error(`Error in request to ${url}: ${err}`);
return;
}
if (response.body) {
logger.info(`Request to ${url} successful.`)
let jsonResult = {};
try {
jsonResult = JSON.parse(response.body);
} catch (e) {
logger.error(`Could not parse.`);
}
logger.info(`Response body for ${gameid} is ${Object.keys(jsonResult).length}.`);
let allItemsArray = Object.keys(jsonResult).map((key, index) => {
return {
game_id: gameid,
market_hash_name: key,
price: jsonResult[key]
}
});
let bulk = Price.collection.initializeUnorderedBulkOp();
allItemsArray.forEach(item => {
bulk.find({market_hash_name: item.market_hash_name})
.upsert().updateOne(item);
});
bulk.execute((err, bulkers) => {
if (err) {
return logger.error(`Error bulking: ${e}`);
}
logger.info(`Updated Items for ${gameid}`)
});
// Price.insertMany(allItemsArray).then(docs => {
// logger.info(`Saved docs for ${gameid}`)
// }, (e) => {
// logger.error(`Error saving docs.`);
// });
}
}
if (cb && typeof cb == 'function') {
cb();
}
})
});
}
现在请注意批量变量(感谢@Rahul),但现在,该集合需要很长时间才能更新。我的处理器正在烧毁,更新 60k 多个文档实际上需要 3 分钟以上的时间。老实说,我觉得像以前的方法,虽然它可能会删除所有它们然后重新插入它们,但速度也快了 10 倍。
有人吗?
【问题讨论】:
-
不是每次使用MongoDB的bulk upsert都删除和添加数据,另一件事是不要在100/1000的chunk中完成_request返回的数据。
-
感谢您的评论,我已经更新了我的问题。现在想看看吗?
标签: javascript node.js mongodb mongoose promise