使用express和node在mongodb中快速高效地分页

yhived7q  于 2023-01-20  发布在  Go
关注(0)|答案(1)|浏览(133)

我在mongodb中有一个名为product的集合,里面有超过200万个产品,我只想从第一个文档到最后一个文档分页,不需要过滤,不需要排序。
我使用了skip()和limit(),但是随着skip()值的增大,响应时间呈指数增长。

app.get('/products', async (req, res) => {
try {
        var query = isNaN(req.query.page) ? 0 : req.query.page <= 0 ? 0 : parseInt(req.query.page) || 0;
        const productPerPage = 20;
        var totalPages = Product.countDocument();
        totalPages = Math.floor(totalPages / 20);
        query = query > totalPages ? totalPages : query;
        const data = await Product.find()
        .sort({_id:1})
        .skip(query * productPerPage)
        .limit(productPerPage)
        res.status(200).render('products', { data, currPage:query, totalPages});
        } catch (error) {
        console.error(error.message);
        res.status(500).send("Internal Server Error");
        }
} ```

its working proper but when the database gets larger the response time gets greater.
kx5bkwkv

kx5bkwkv1#

使用skip和limit进行分页意味着数据库服务器需要加载匹配的文档,对它们进行排序,然后应用skip和limit。
{_id:1}上使用排序将允许服务器以预先排序的顺序从索引中读取_id值,而不是内存中排序,但是它仍然需要扫描所有值,以便找到第一个要返回的值,即,在第一次调用时,它将从第一个文档开始并返回20,在第二次调用时,它将读取40个文档,丢弃前20个并返回20个,以此类推。2所以在最后一次调用时,它将读取所有200万个文档并丢弃其中的1,999,980个。3这就是为什么它在后面的页面上要慢得多的原因。
还有一些性能更好的分页方法,例如,如果应用程序在请求中包含previous _id值,路由可以查询Product.find({_id:{$gt: ObjectId(req.query.lastseen)}}).sort({_id:1}).limit(productPerPage),而不是只请求页码,这样既可以有更可预测的运行时间,又不会因为在调用之间删除文档而丢失文档。

相关问题