你好,
我使用Node.js提供了一个用于在MongoDB数据库上存储数据的API。
我对一个read
方法进行了多个测试,该方法使用id并返回相应的文档。关键是我必须按指定顺序退回这些文件。为了确保这一点,我使用以下代码:
// Sequentially fetch every element
function read(ids, callback) {
var i = 0;
var results = [];
function next() {
db.findOne(ids[i], function (err, doc) {
results.push(err ? null : doc);
if (ids.length > ++i) {
return next();
}
callback(results);
});
}
next();
}
这样,可以以正确的顺序一张一张地提取文档。我的笔记本电脑上大约需要11秒钟才能检索到27k个文档。
但是,我认为可以改进此方法:
// Asynchronously map the whole array
var async = require('async');
function read(ids, callback) {
async.map(ids, db.findOne.bind(db), callback):
}
在运行了一个测试之后,我很满意地看到使用更简单的代码仅用8秒钟就检索到27k文档。
当我重复相同的请求的问题发生:响应时间不断增加(成比例的元素检索到的数): 9s 10s 11s 12s...
。在顺序版本中不会发生此问题。
我尝试了两个版本的Node.js,分别是v6.2.0和v0.10.29。问题是一样的。是什么导致了这种延迟,我该如何抑制呢?
尝试使用async.mapLimit
以防止过载。您需要进行一些测试,以根据环境调整极限值。
但是find({_id: {$in: list}})
总会更好,因为单个数据库请求而不是多个数据库请求。
我建议您尝试执行原始订单客户端的还原。
像这样的东西:
function read(ids, cb) {
db.find(
{_id: {$in: ids.map(id => mongoose.Types.ObjectId(id))}},
process
);
function process(err, docs) {
if (err) return cb(err);
return cb(null, docs.sort(ordering))
}
function ordering(a, b) {
return ids.indexOf(b._id.toString()) - ids.indexOf(a._id.toString());
}
}
可能是,查找查询需要更正,我不知道您使用了什么确切的mongodb驱动程序。
该代码是第一个尝试的代码,更多的手动排序可以大大提高性能。[].indexOf
也很重(O(n)
)。
但我几乎可以肯定,即使现在,它的运行速度也要快得多。
可能的ordering
替换:
var idHash = {};
for(var i = 0; i < ids.length; i++)
idHash[ids[i]] = i;
function ordering(a, b) {
return idHash[b._id.toString()] - idHash[a._id.toString()];
}
任何排序算法O(nlogn)
在最佳情况下都有,但是我们已经知道每个找到的文档的结果位置,因此,我们可以通过O(n)
以下方法恢复原始顺序:
var idHash = ids.reduce((c, id, i) => (c[id] = i, c), {});
function process(err, docs) {
if (err) return cb(err);
return cb(null,
docs.reduce(
(c, doc) => (c[idHash[doc._id.toString()]] = doc, c),
ids.map(id => null))) //fill not_found docs by null
}
功能风格使代码更加灵活。例如,可以轻松修改此代码async.reduce
以减少同步阻塞。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句