sql >> Database teknologi >  >> NoSQL >> MongoDB

Implementering af paginering i mongodb

Konceptet du taler om kan kaldes "forward paging". En god grund til det er i modsætning til at bruge .skip() og .limit() modifikatorer dette kan ikke bruges til at "gå tilbage" til en tidligere side eller faktisk "springe over" til en bestemt side. I hvert fald ikke med en stor indsats for at gemme "sete" eller "opdagede" sider, så hvis den type "links til side"-sidesøgning er, hvad du ønsker, så er det bedst at du holder dig til .skip() og .limit() tilgang på trods af præstationsmanglerne.

Hvis det er en farbar mulighed for dig kun at "gå fremad", så er her det grundlæggende koncept:

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 }

Det er selvfølgelig din første side med en grænse på 3 elementer. Overvej det nu med kode, der gentager markøren:

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;
}

Så det gentager markøren og gør noget, og når det er sandt, at det sidste punkt i markøren er nået, gemmer du lastSeen værdi til det nuværende _id :

ObjectId("54c03f0c2f63310180151879")

I dine efterfølgende iterationer fodrer du bare det _id værdi, som du beholder (i session eller hvad som helst) til forespørgslen:

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 }

Og processen gentages igen og igen, indtil der ikke kan opnås flere resultater.

Det er den grundlæggende proces for en naturlig orden såsom _id . For noget andet bliver det lidt mere komplekst. Overvej følgende:

{ "_id": 4, "rank": 3 }
{ "_id": 8, "rank": 3 }
{ "_id": 1, "rank": 3 }    
{ "_id": 3, "rank": 2 }

For at opdele det i to sider sorteret efter rangering, så er det, du i bund og grund har brug for at vide, hvad du "allerede har set" og udelukker disse resultater. Så ser på en første side:

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 }

Ved den næste iteration vil du være mindre eller lig med den sidst sete "rangering", men også ekskludere de allerede sete dokumenter. Du gør dette med $nin operatør:

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 }

Hvor mange "seenIds" du rent faktisk holder på afhænger af, hvor "granulære" dine resultater er, hvor værdien sandsynligvis vil ændre sig. I dette tilfælde kan du kontrollere, om den aktuelle "rang"-score ikke er lig med lastSeen værdi og kasser de nuværende seenIds indhold, så det ikke vokser for meget.

Det er de grundlæggende begreber for "fremadsøgning", som du kan øve dig på og lære.



  1. Lyt efter ændringer i Redis?

  2. Mongoose og multiple database i enkelt node.js projekt

  3. Mongoose.js:Find bruger efter brugernavn LIKE værdi

  4. MongoDB $min