在 Mongoose 和 Keystone 中,包含许多元素的分页速度非常慢
Pagination with many elements is incredibly slow in Mongoose and Keystone
版本:Keystone v4
我有一个 Mongo 数据库,其中包含超过 20k 个项目。我想要的是一个分页器,它允许用户一次快速滚动 Mongo 数据库 25 个元素。目前,此功能已实现,但服务器需要 >40 秒才能 return 结果,因为它查询整个(20k 项)数据库。但是,单个页面上只显示 25 个元素,所以我觉得如果只获取 25 个结果而不是 20k,应该会更快。我怎么能实现这个?我知道 .limit()
函数,但在使用该函数时我似乎无法弄清楚 keystone 中的分页。
当前代码:
var q = Items.model.find();
q.exec(function(err, newss) {
console.log('There are %d', newss.length); // Prints out 20k number
...//skip
locals.cnts = newss;
// console.log(newss[0])
locals.pagerr = pager({
page: parseInt(req.query.page, 10) || 1,
perPage: 25,
total: newss.length
});
locals.itemsss = locals.cnts.slice(
locals.pagerr.first - 1,
locals.pagerr.last
);
next();
})
在当前的实现中,return 分页结果需要 >40 秒。我该如何解决这个问题?
您在此处使用的 model.find()
函数等同于 Mongoose find()
function。由于您在没有任何过滤器的情况下调用它,此代码每次 运行 时都会 从数据库 中检索所有 25k 项。此数据正在传输到 Web server/node 进程,其中 function(err, newss) {...}
函数的主体是 运行。只有 然后 是你从集合中提取后的 25 个项目。
相反,如果你想像这样使用基于偏移量的分页,你应该使用 query.limit()
and query.skip()
functions. If you need to count the total items first, do so in a separate query using query.count()
.
我还没有测试过这段代码(自从我使用 Mongoose 以来已经有一段时间了),但我想你想要这样的东西:
// Warning! Untested example code
Items.model.find().count(function (err, count) {
console.log('There are %d', count);
locals.pager = pager({
page: parseInt(req.query.page, 10) || 1,
perPage: 25,
total: count
});
Items.model.find()
.skip(locals.pager.first)
.limit(25)
.exec(function(err, results) {
locals.results = results;
next();
});
});
更笼统地说——如果您喜欢 Keystone 并想使用 Mongo,请留意 Keystone 6 updates. Keystone 6 uses Prisma 2 as it's ORM layer and they recently released support for Mongo。一旦该功能生产准备就绪,我们也会在 Keystone 中支持它。
版本:Keystone v4
我有一个 Mongo 数据库,其中包含超过 20k 个项目。我想要的是一个分页器,它允许用户一次快速滚动 Mongo 数据库 25 个元素。目前,此功能已实现,但服务器需要 >40 秒才能 return 结果,因为它查询整个(20k 项)数据库。但是,单个页面上只显示 25 个元素,所以我觉得如果只获取 25 个结果而不是 20k,应该会更快。我怎么能实现这个?我知道 .limit()
函数,但在使用该函数时我似乎无法弄清楚 keystone 中的分页。
当前代码:
var q = Items.model.find();
q.exec(function(err, newss) {
console.log('There are %d', newss.length); // Prints out 20k number
...//skip
locals.cnts = newss;
// console.log(newss[0])
locals.pagerr = pager({
page: parseInt(req.query.page, 10) || 1,
perPage: 25,
total: newss.length
});
locals.itemsss = locals.cnts.slice(
locals.pagerr.first - 1,
locals.pagerr.last
);
next();
})
在当前的实现中,return 分页结果需要 >40 秒。我该如何解决这个问题?
您在此处使用的 model.find()
函数等同于 Mongoose find()
function。由于您在没有任何过滤器的情况下调用它,此代码每次 运行 时都会 从数据库 中检索所有 25k 项。此数据正在传输到 Web server/node 进程,其中 function(err, newss) {...}
函数的主体是 运行。只有 然后 是你从集合中提取后的 25 个项目。
相反,如果你想像这样使用基于偏移量的分页,你应该使用 query.limit()
and query.skip()
functions. If you need to count the total items first, do so in a separate query using query.count()
.
我还没有测试过这段代码(自从我使用 Mongoose 以来已经有一段时间了),但我想你想要这样的东西:
// Warning! Untested example code
Items.model.find().count(function (err, count) {
console.log('There are %d', count);
locals.pager = pager({
page: parseInt(req.query.page, 10) || 1,
perPage: 25,
total: count
});
Items.model.find()
.skip(locals.pager.first)
.limit(25)
.exec(function(err, results) {
locals.results = results;
next();
});
});
更笼统地说——如果您喜欢 Keystone 并想使用 Mongo,请留意 Keystone 6 updates. Keystone 6 uses Prisma 2 as it's ORM layer and they recently released support for Mongo。一旦该功能生产准备就绪,我们也会在 Keystone 中支持它。