Konsep yang Anda bicarakan dapat disebut "forward paging". Alasan bagus untuk itu tidak seperti menggunakan .skip()
dan .limit()
modifier ini tidak bisa digunakan untuk "kembali" ke halaman sebelumnya atau memang "melompat" ke halaman tertentu. Setidaknya tidak dengan banyak usaha untuk menyimpan halaman yang "terlihat" atau "ditemukan", jadi jika jenis halaman "tautan ke halaman" itu yang Anda inginkan, maka sebaiknya Anda tetap menggunakan .skip()
dan .limit()
pendekatan, meskipun ada kelemahan kinerja.
Jika ini adalah pilihan yang layak bagi Anda untuk hanya "bergerak maju", maka inilah konsep dasarnya:
db.junk.find().limit(3)
{ "_id" : ObjectId("54c03f0c2f63310180151877"), "a" : 1, "b" : 1 }
{ "_id" : ObjectId("54c03f0c2f63310180151878"), "a" : 4, "b" : 4 }
{ "_id" : ObjectId("54c03f0c2f63310180151879"), "a" : 10, "b" : 10 }
Tentu saja itu halaman pertama Anda dengan batas 3 item. Pertimbangkan bahwa sekarang dengan kode iterasi kursor:
var lastSeen = null;
var cursor = db.junk.find().limit(3);
while (cursor.hasNext()) {
var doc = cursor.next();
printjson(doc);
if (!cursor.hasNext())
lastSeen = doc._id;
}
Sehingga mengulangi kursor dan melakukan sesuatu, dan ketika benar bahwa item terakhir dalam kursor tercapai, Anda menyimpan lastSeen
nilai ke _id
present saat ini :
ObjectId("54c03f0c2f63310180151879")
Dalam iterasi berikutnya, Anda hanya memberi makan _id
nilai yang Anda simpan ( dalam sesi atau apa pun ) ke kueri:
var cursor = db.junk.find({ "_id": { "$gt": lastSeen } }).limit(3);
while (cursor.hasNext()) {
var doc = cursor.next();
printjson(doc);
if (!cursor.hasNext())
lastSeen = doc._id;
}
{ "_id" : ObjectId("54c03f0c2f6331018015187a"), "a" : 1, "b" : 1 }
{ "_id" : ObjectId("54c03f0c2f6331018015187b"), "a" : 6, "b" : 6 }
{ "_id" : ObjectId("54c03f0c2f6331018015187c"), "a" : 7, "b" : 7 }
Dan proses itu berulang-ulang sampai tidak ada lagi hasil yang bisa didapatkan.
Itulah proses dasar untuk tatanan alam seperti _id
. Untuk sesuatu yang lain itu menjadi sedikit lebih kompleks. Pertimbangkan hal berikut:
{ "_id": 4, "rank": 3 }
{ "_id": 8, "rank": 3 }
{ "_id": 1, "rank": 3 }
{ "_id": 3, "rank": 2 }
Untuk membaginya menjadi dua halaman yang diurutkan berdasarkan peringkat, maka yang pada dasarnya perlu Anda ketahui adalah apa yang "sudah Anda lihat" dan mengecualikan hasil tersebut. Jadi melihat halaman pertama:
var lastSeen = null;
var seenIds = [];
var cursor = db.junk.find().sort({ "rank": -1 }).limit(2);
while (cursor.hasNext()) {
var doc = cursor.next();
printjson(doc);
if ( lastSeen != null && doc.rank != lastSeen )
seenIds = [];
seenIds.push(doc._id);
if (!cursor.hasNext() || lastSeen == null)
lastSeen = doc.rank;
}
{ "_id": 4, "rank": 3 }
{ "_id": 8, "rank": 3 }
Pada iterasi berikutnya Anda ingin kurang atau sama dengan skor "peringkat" terakhir, tetapi juga mengecualikan dokumen yang sudah terlihat. Anda melakukannya dengan $nin
operator:
var cursor = db.junk.find(
{ "_id": { "$nin": seenIds }, "rank": "$lte": lastSeen }
).sort({ "rank": -1 }).limit(2);
while (cursor.hasNext()) {
var doc = cursor.next();
printjson(doc);
if ( lastSeen != null && doc.rank != lastSeen )
seenIds = [];
seenIds.push(doc._id);
if (!cursor.hasNext() || lastSeen == null)
lastSeen = doc.rank;
}
{ "_id": 1, "rank": 3 }
{ "_id": 3, "rank": 2 }
Berapa banyak "seenIds" yang sebenarnya Anda pegang bergantung pada seberapa "granular" hasil Anda di mana nilai itu kemungkinan akan berubah. Dalam hal ini Anda dapat memeriksa apakah skor "peringkat" saat ini tidak sama dengan lastSeen
nilai dan buang seenIds
. yang ada konten agar tidak tumbuh terlalu banyak.
Itulah konsep dasar "forward paging" untuk Anda praktikkan dan pelajari.