Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> MongoDB

Triển khai Phân trang (Pagination) trong MongoDB với skip() và limit()

Phân trang cơ bản trong MongoDB sử dụng cặp skip() và limit().

Công thức

  • skip((page - 1) * pageSize)
  • limit(pageSize)

Ví dụ minh họa

Tạo collection paginationDemo 5 document:

> db.paginationDemo.insertOne({ "CustomerName": "Chris", "CustomerAge": 23 });
> db.paginationDemo.insertOne({ "CustomerName": "Robert", "CustomerAge": 26 });
> db.paginationDemo.insertOne({ "CustomerName": "David", "CustomerAge": 24 });
> db.paginationDemo.insertOne({ "CustomerName": "Carol", "CustomerAge": 28 });
> db.paginationDemo.insertOne({ "CustomerName": "Bob", "CustomerAge": 29 });

Hiển thị tất cả:

> db.paginationDemo.find().pretty();

Trang 1: PageSize = 3

> db.paginationDemo.find().skip(0).limit(3);

Kết quả: 3 document đầu (Chris, Robert, David).

{ "_id" : ..., "CustomerName" : "Chris", "CustomerAge" : 23 }
{ "_id" : ..., "CustomerName" : "Robert", "CustomerAge" : 26 }
{ "_id" : ..., "CustomerName" : "David", "CustomerAge" : 24 }

Trang 2: PageSize = 3

> db.paginationDemo.find().skip(3).limit(3);

Kết quả: 2 document còn lại (Carol, Bob).

Code mẫu áp dụng (JavaScript/Node.js)

async function getPage(page, pageSize) {
    const skip = (page - 1) * pageSize;
    const data = await db.collection.find().skip(skip).limit(pageSize).toArray();
    const total = await db.collection.countDocuments();
    return { data, total, page, pageSize, totalPages: Math.ceil(total / pageSize) };
}

Vấn đề hiệu suất với skip() lớn

skip() phải quét qua N document đầu tiên -> **chậm dần khi trang sâu** (deep pagination).

Giải pháp tối ưu: Keyset Pagination (Cursor-based)

Dùng field sort unique (thường là _id hoặc createdAt) làm "con trỏ":

// Trang đầu
db.coll.find().sort({ _id: 1 }).limit(3);

// Trang sau: dùng _id của document cuối trang trước
db.coll.find({ _id: { $gt: lastId } }).sort({ _id: 1 }).limit(3);
  • Hiệu suất O(1) không phụ thuộc vào số trang.
  • Yêu cầu field sort có index và unique (hoặc compound unique).
  • Không hỗ trợ "nhảy đến trang N" tùy ý (chỉ next/prev).

Tóm tắt khi nào dùng cách nào

Phương phápƯu điểmNhược điểmPhù hợp
skip/limitĐơn giản, nhảy trang tùy ýChậm khi trang sâuAdmin UI, dữ liệu ít (<10k docs)
Keyset ($gt/_id)Nhanh, ổn địnhKhông nhảy trang tùy ýAPI mobile, feed vô hạn, big data