Layar pencarian toko buku menampilkan 20 hasil per halaman, laporan dashboard hanya butuh 10 produk teratas, dan pengguna mengeklik “halaman 4” untuk melihat hasil berikutnya. Tiga kebutuhan itu dipenuhi dua method cursor: limit() memotong jumlah hasil, skip() melompati sejumlah document di depan. Keduanya dijalankan di sisi server sebelum data dikirim, sehingga jaringan hanya membawa hasil akhir. Chapter ini membahas keduanya, kombinasi untuk paging, dan biaya tersembunyi saat skip() menjadi sangat besar.
Peta materi Chapter ini:
limit()danskip()secara terpisah.- Urutan penulisan rantai method yang tidak memengaruhi hasil.
- Pola paging
skip-limitbeserta batasannya.
Data Uji dan limit() #
Katalog yang sama dengan Chapter Sorting dipakai lagi:
use latihan_query
db.buku.drop()Output yang Dihasilkan:
switched to db latihan_query
truedb.buku.insertMany([
{ judul: "Laut Bercerita", penulis: "Leila S. Chudori", harga: 98000, stok: 12, kategori: "fiksi", rating: 4.7 },
{ judul: "Bumi", penulis: "Tere Liye", harga: 89000, stok: 25, kategori: "fiksi", rating: 4.5 },
{ judul: "Filosofi Teras", penulis: "Henry Manampiring", harga: 89000, stok: 18, kategori: "nonfiksi", rating: 4.8 },
{ judul: "Atomic Habits", penulis: "James Clear", harga: 115000, stok: 30, kategori: "nonfiksi", rating: 4.6 },
{ judul: "Rumah Kaca", penulis: "Tere Liye", harga: 72000, stok: 9, kategori: "fiksi", rating: 4.3 },
{ judul: "Kamus Bahasa Indonesia", penulis: "Badan Bahasa", harga: 55000, stok: 4, kategori: "referensi" }
])Output yang Dihasilkan:
{
acknowledged: true,
insertedIds: {
'0': ObjectId('6ad38fcb888d26aa72dec926'),
'1': ObjectId('6ad38fcb888d26aa72dec927'),
'2': ObjectId('6ad38fcb888d26aa72dec928'),
'3': ObjectId('6ad38fcb888d26aa72dec929'),
'4': ObjectId('6ad38fcb888d26aa72dec92a'),
'5': ObjectId('6ad38fcb888d26aa72dec92b')
}
}limit(n) membatasi jumlah document yang dikirim ke klien. Tiga buku termurah — hasil sort() lalu dipotong:
db.buku.find({}, { _id: 0, judul: 1, harga: 1 }).sort({ harga: 1 }).limit(3)Output yang Dihasilkan:
[
{ judul: 'Kamus Bahasa Indonesia', harga: 55000 },
{ judul: 'Rumah Kaca', harga: 72000 },
{ judul: 'Filosofi Teras', harga: 89000 }
]Karena pengurutan dan pemotongan terjadi di server, kombinasi sort().limit() hanya mengirim tiga document — bukan seluruh katalog lalu dipotong di aplikasi. Pola ini adalah bentuk query paling umum untuk daftar “top N”.
skip(n) melompati n document pertama sebelum mulai mengirim. Ambil hasil setelah tiga buku termurah:
db.buku.find({}, { _id: 0, judul: 1, harga: 1 }).sort({ harga: 1 }).skip(3)Output yang Dihasilkan:
[
{ judul: 'Filosofi Teras', harga: 89000 },
{ judul: 'Laut Bercerita', harga: 98000 },
{ judul: 'Atomic Habits', harga: 115000 }
]Urutan Rantai Tidak Penting #
Dua penulisan berikut terlihat berbeda, tetapi hasilnya identik:
db.buku.find({}, { _id: 0, judul: 1, harga: 1 }).sort({ harga: 1 }).skip(1).limit(2)
db.buku.find({}, { _id: 0, judul: 1, harga: 1 }).sort({ harga: 1 }).limit(2).skip(1)Output yang Dihasilkan:
[
{ judul: 'Rumah Kaca', harga: 72000 },
{ judul: 'Filosofi Teras', harga: 89000 }
]
[
{ judul: 'Rumah Kaca', harga: 72000 },
{ judul: 'Filosofi Teras', harga: 89000 }
]Kedua baris mengembalikan pasangan Rumah Kaca dan Filosofi Teras. Cursor di mongosh hanya menyimpan opsi-opsi query; saat data benar-benar ditarik (dicetak, di-toArray(), atau di-forEach()), seluruh opsi dikirim sebagai satu perintah find ke server, dan server yang menentukan urutan penerapannya: filter → sort → skip → limit. Kita bebas menulis rantai dengan urutan yang paling terbaca di kode.
Paging: Halaman demi Halaman #
Kombinasi skip dan limit adalah rumus paging klasik: skip = (nomorHalaman - 1) × ukuranHalaman. Dengan ukuran halaman 2, tiga halaman pertama dari daftar harga menaik:
db.buku.find({}, { _id: 0, judul: 1, harga: 1 }).sort({ harga: 1 }).limit(2)
db.buku.find({}, { _id: 0, judul: 1, harga: 1 }).sort({ harga: 1 }).skip(2).limit(2)
db.buku.find({}, { _id: 0, judul: 1, harga: 1 }).sort({ harga: 1 }).skip(4).limit(2)Output yang Dihasilkan:
[
{ judul: 'Kamus Bahasa Indonesia', harga: 55000 },
{ judul: 'Rumah Kaca', harga: 72000 }
]
[
{ judul: 'Bumi', harga: 89000 },
{ judul: 'Filosofi Teras', harga: 89000 }
]
[
{ judul: 'Laut Bercerita', harga: 98000 },
{ judul: 'Atomic Habits', harga: 115000 }
]Enam buku terbagi rapi menjadi tiga halaman berisi dua document. Jika skip melewati seluruh hasil, query tidak error — cursor hanya kehabisan document:
db.buku.find({}, { _id: 0, judul: 1 }).sort({ harga: 1 }).skip(50).toArray()Output yang Dihasilkan:
[]toArray() mengembalikan array kosong, bukan pesan error. Perilaku ini membuat nomor halaman yang terlalu besar cukup ditangani sebagai “tidak ada data” di aplikasi.
Biaya skip yang Besar #
Di balik kesederhanaannya, skip(n) punya harga: server tetap harus membaca dan membuang n document pertama sebelum mengirim hasilnya. Halaman 1 dari katalog 1000 buku murah; halaman 500 (skip(998000) pada katalog sejuta) memaksa server menelusuri hampir sejuta document hanya untuk dibuang.
Untuk kebutuhan sehari-hari — halaman awal, daftar top N, pratinjau data — kombinasi sort().skip().limit() sudah tepat: sederhana, dijalankan di server, dan cukup cepat pada data yang tidak terlalu dalam.
Rangkuman #
limit(n)memotong jumlah hasil;skip(n)melompati n document pertama — keduanya dijalankan di server.- Urutan penulisan rantai (
skip().limit()ataulimit().skip()) tidak memengaruhi hasil; server menerapkan skip sebelum limit. - Rumus paging:
skip = (nomorHalaman - 1) × ukuranHalaman;skipmelebihi jumlah hasil mengembalikan cursor kosong tanpa error. skip()besar membebani server karena document yang dilompati tetap dibaca; deep paging sebaiknya memakai cursor-based pagination.