Nodejs MongoDB关于不使用skip进行分页

Nodejs MongoDB关于不使用skip进行分页

MongoDB权威指南给出了这样的分页示例

一般来讲可以找到一种方法不用skip的分页,这取决于查询本身。例如,要按照"date"降序显示文档。可以用如下方式获取结果的第一页:
> var page1=db.foo.find().sort({"date":-1}).limit(100)
然后,可以利用最后一个文档中"date"的值作为查询条件,来获取下一页:
var latest=null;

//display first page
while(page1.hasNext()){
    latest=page1.next();
    display(latest);
}

//get next page
var page2=db.foo.find({"date":{"$gt":latest.date}});//游标已下移动,当前游标位置为下一页的第一项
page2.sort({"date":-1}).limit(100);

这里只是手动的分了两页,如果想应用到程序中该如何实现呢?每页100个数据,如果我想看第7页的数据,是不是应该以传入参数的形式,如:paging(100,6)来进行呢?

var pageSize; var page; var page1=db.foo.find().sort({“date”:-1}).limit(pageSize*page)

有实际操作过的前辈吗?


5 回复

Node.js MongoDB 关于不使用 skip 进行分页

背景

在 MongoDB 中,传统的分页方法通常会使用 skip 方法来跳过前面的数据,但这种方法在大数据集上性能较差。因此,我们可以采用一种更高效的方法,即利用前一页的最后一条记录的字段值(例如时间戳)来获取下一页的数据。

示例代码

以下是一个 Node.js 示例,展示了如何不使用 skip 来实现分页功能。假设我们有一个集合 posts,并且我们希望按时间戳降序排序。

const MongoClient = require('mongodb').MongoClient;

async function paging(pageSize, pageNumber) {
    const uri = "your_mongodb_connection_string";
    const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });

    try {
        await client.connect();
        const db = client.db("your_database_name");
        const collection = db.collection("posts");

        // 获取上一页的最后一条记录的时间戳
        let lastDateOfPreviousPage;
        if (pageNumber > 1) {
            const previousPage = await collection.find()
                .sort({ date: -1 })
                .limit(pageSize * (pageNumber - 1))
                .toArray();
            lastDateOfPreviousPage = previousPage[pageSize - 1].date;
        }

        // 获取当前页的数据
        const currentPage = await collection.find({
            date: { $lt: lastDateOfPreviousPage }
        })
        .sort({ date: -1 })
        .limit(pageSize)
        .toArray();

        console.log(currentPage);
    } catch (error) {
        console.error("Error:", error);
    } finally {
        await client.close();
    }
}

// 测试函数
paging(100, 7); // 查看第7页的数据

解释

  1. 连接数据库:首先连接到 MongoDB 数据库。
  2. 获取上一页的最后一条记录:如果需要查看的是第一页以外的页面,则需要先获取上一页的最后一条记录的时间戳。
  3. 获取当前页的数据:根据上一页的最后一条记录的时间戳,查询当前页的数据。使用 $lt 操作符来确保只获取比上一页最后一条记录时间戳小的数据。
  4. 排序和限制结果:对结果进行降序排序,并限制返回的结果数量。

通过这种方式,我们可以避免使用 skip 方法,从而提高分页查询的性能。


以游标作分页的话,应该不能随意换页,须以$gt$lt查询 因为没有游标,所以想看第7页只能用skip

大哥你好 这个书上不使用skip的示例只给出了第一页和第二页,再往后该怎么弄我就想不出来了 赏我个思路呗

可以参考 https://developers.facebook.com/docs/reference/api/pagination/ 以express为例:

exports.getItem = function(req, res){
  var cursor = {};
  if(req.query){
  	if(req.query.until)cursor.$lt = req.query.until;
  	if(req.query.since)cursor.$gt = req.query.since;
  }
  db.col.find({"date": cursor},).toArray(function(err, item){
    //...
  })
}

在Node.js中使用MongoDB时,不使用skip()方法进行分页是一种常见的优化策略,特别是在处理大量数据时。这是因为skip()方法会跳过指定数量的文档,对于大数据集来说效率较低。下面将通过一个具体的示例来展示如何使用这种方式进行分页。

示例代码

首先,我们需要安装mongodb库(如果你还没有安装的话):

npm install mongodb

接下来是实现分页功能的代码示例:

const { MongoClient } = require('mongodb');

async function fetchPage(url, pageSize, pageNumber) {
    const client = new MongoClient(url, { useNewUrlParser: true, useUnifiedTopology: true });
    
    try {
        await client.connect();
        const db = client.db('yourDatabaseName');
        const collection = db.collection('yourCollectionName');
        
        let cursor = collection.find();

        // 获取上一页的最后一条记录
        if (pageNumber > 1) {
            const lastDoc = await collection.findOne({}, { sort: { date: -1 }, skip: (pageNumber - 1) * pageSize });
            cursor = collection.find({ date: { $lt: lastDoc.date } });
        }

        cursor = cursor.sort({ date: -1 }).limit(pageSize);

        const result = await cursor.toArray();
        return result;
    } finally {
        await client.close();
    }
}

// 调用函数
fetchPage('mongodb://localhost:27017', 100, 7).then(data => console.log(data));

解释

  • fetchPage 函数: 这是一个异步函数,接收数据库连接字符串、每页大小和页码作为参数。

  • 查找上一页的最后一项: 如果需要查看的不是第一页,我们先找到上一页的最后一条记录,并用它的日期作为条件来查询下一页的数据。

  • sortlimit 方法: 使用这两个方法对结果进行排序并限制返回的文档数量,模拟skip效果。

这种方法避免了使用skip,提升了查询效率,特别适合于数据量大的场景。希望这个示例能帮助您理解如何在Node.js中实现无skip的分页功能。

回到顶部