使用MongoDB时,是否有任何特殊模式可用于制作分页视图?说一个博客列出了10个最新帖子,你可以向后导航到较旧的帖子.
或者用例如blogpost.publishdate上的索引来解决它,然后跳过并限制结果?
Sco*_*dez 93
使用skip + limit不是在性能问题或大型集合时进行分页的好方法; 当你增加页码时,它会越来越慢.使用skip需要服务器遍历从0到偏移(跳过)值的所有文档(或索引值).
最好使用范围查询(+ limit)传递最后一页的范围值.例如,如果按"publishdate"排序,则可以简单地将最后一个"publishdate"值作为查询的条件传递,以获取下一页数据.
jac*_*ope 11
可能的解决方案:尝试简化设计,考虑我们是否只能按id或某些唯一值排序?
如果可以的话,可以使用基于范围的分页.
常见的方法是使用sort(),skip()和limit()来实现上面描述的分页.
这是我在我的集合变得太大而无法在单个查询中返回时使用的解决方案.它利用了_id字段的固有顺序,允许您按指定的批处理大小循环访问集合.
这里是一个npm模块,mongoose-paging,完整代码如下:
function promiseWhile(condition, action) {
return new Promise(function(resolve, reject) {
process.nextTick(function loop() {
if(!condition()) {
resolve();
} else {
action().then(loop).catch(reject);
}
});
});
}
function findPaged(query, fields, options, iterator, cb) {
var Model = this,
step = options.step,
cursor = null,
length = null;
promiseWhile(function() {
return ( length===null || length > 0 );
}, function() {
return new Promise(function(resolve, reject) {
if(cursor) query['_id'] = { $gt: cursor };
Model.find(query, fields, options).sort({_id: 1}).limit(step).exec(function(err, items) {
if(err) {
reject(err);
} else {
length = items.length;
if(length > 0) {
cursor = items[length - 1]._id;
iterator(items, function(err) {
if(err) {
reject(err);
} else {
resolve();
}
});
} else {
resolve();
}
}
});
});
}).then(cb).catch(cb);
}
module.exports = function(schema) {
schema.statics.findPaged = findPaged;
};
Run Code Online (Sandbox Code Playgroud)
将它附加到您的模型,如下所示:
MySchema.plugin(findPaged);
Run Code Online (Sandbox Code Playgroud)
然后像这样查询:
MyModel.findPaged(
// mongoose query object, leave blank for all
{source: 'email'},
// fields to return, leave blank for all
['subject', 'message'],
// number of results per page
{step: 100},
// iterator to call on each set of results
function(results, cb) {
console.log(results);
// this is called repeatedly while until there are no more results.
// results is an array of maximum length 100 containing the
// results of your query
// if all goes well
cb();
// if your async stuff has an error
cb(err);
},
// function to call when finished looping
function(err) {
throw err;
// this is called once there are no more results (err is null),
// or if there is an error (then err is set)
}
);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
51178 次 |
| 最近记录: |