MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Implementacja paginacji w mongodb

Koncepcję, o której mówisz, można nazwać „przekierowywaniem”. Dobry powód jest inny niż użycie .skip() i .limit() modyfikatory, których nie można użyć do "powrotu" do poprzedniej strony lub rzeczywiście "przeskoku" do określonej strony. Przynajmniej nie przy dużym wysiłku, aby przechowywać „odkryte” lub „odkryte” strony, więc jeśli tego typu stronicowanie „łącza do strony” jest tym, czego potrzebujesz, najlepiej jest trzymać się .skip() i .limit() podejście, pomimo wad wydajności.

Jeśli rozsądną opcją jest tylko „poruszanie się do przodu”, oto podstawowa koncepcja:

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 }

Oczywiście to Twoja pierwsza strona z limitem 3 pozycji. Rozważ to teraz z kodem iterującym 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;
}

Aby iterować kursor i coś robić, a kiedy prawdą jest, że ostatni element w kursorze został osiągnięty, przechowujesz lastSeen wartość na obecny _id :

ObjectId("54c03f0c2f63310180151879")

W kolejnych iteracjach po prostu podajesz ten _id wartość, którą zachowujesz (w sesji lub cokolwiek) w zapytaniu:

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 }

A proces powtarza się w kółko, aż nie można uzyskać więcej wyników.

To podstawowy proces dla porządku naturalnego, takiego jak _id . Z powodu czegoś innego sprawa staje się nieco bardziej skomplikowana. Rozważ następujące kwestie:

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

Aby podzielić to na dwie strony posortowane według pozycji, musisz zasadniczo wiedzieć, co „już widziałeś” i wykluczyć te wyniki. Patrząc na pierwszą stronę:

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 }

W następnej iteracji chcesz być mniejszy lub równy wynikowi lastSeen „rank”, ale także z wyłączeniem tych, które już widziałeś. Robisz to za pomocą $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 }

Liczba „widzianych identyfikatorów”, których faktycznie się trzymasz, zależy od tego, jak „ziarniste” są Twoje wyniki, w których ta wartość może się zmienić. W tym przypadku możesz sprawdzić, czy aktualny wynik "rangi" nie jest równy lastSeen wartość i odrzuć obecne seenIds treści, więc nie rozrasta się zbytnio.

To podstawowe koncepcje „przekierowywania do przodu”, aby ćwiczyć i uczyć się.



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Której bazy danych NoSQL powinienem używać do logowania?

  2. MongoDB i CodeIgniter

  3. MongoDB $ceil

  4. MongoDB $dayOfYear

  5. MongoDB i Robomongo:nie można się połączyć (uwierzytelnianie)