2008-11-23 17 views
42

Wie würde ich die für die Paginierung erforderlichen Abfragen implementieren?Seitennummerierung in CouchDB?

Grundsätzlich, wenn Seite 1 angefordert wird, erhalten Sie die ersten 5 Einträge. Für Seite 2, holen Sie sich die nächsten 5 und so weiter.

Ich plane, dies über das Couchdb-Python-Modul zu verwenden, aber das sollte für die Implementierung keinen Unterschied machen.

Antwort

31

Die CouchDB Guide hat eine gute Diskussion über die Paginierung, darunter viele Beispielcode hier: http://guide.couchdb.org/draft/recipes.html#pagination Hier ist ihr Algorithmus:

  • Anfrage rows_per_page + 1 Zeilen aus der Ansicht
  • Anzeige rows_per_page Reihen, speichern letzte Zeile als next_startkey
  • Als Seiteninformationen, halten startkey und next_startkey
  • Über die next_* Werte zum nächsten Link zu erstellen, und die anderen verwenden, um den vorherigen Link

N. B .: Die richtige Art und Weise zu erstellen Seiten zu holen in CouchDB durch die Angabe einer Starttaste, kein Startindex wie Sie vielleicht denken. Aber woher weißt du, welcher Schlüssel zum Start der 2. Seite ist?Die clevere Lösung: "Statt 10 Zeilen für eine Seite anzufordern, fordern Sie 11 Zeilen an, aber nur 10 und verwenden Sie die Werte in der 11. Zeile als Startschlüssel für die nächste Seite." Wenn Sie erwarten, dass mehrere Dokumente identische Schlüssel ausgeben, müssen Sie startdocid zusätzlich zu startkey verwenden, um korrekt zu paginieren. Der Grund ist, dass startkey allein nicht mehr ausreicht, um eine Zeile eindeutig zu identifizieren. Diese Parameter sind nutzlos, wenn Sie keine startkey bereitstellen. Tatsächlich wird CouchDB zuerst den Parameter startkey betrachten und dann den Parameter startdocid verwenden, um den Anfang des Bereichs weiter zu definieren, wenn mehrere potenzielle Startreihen denselben Schlüssel, aber unterschiedliche Dokument-IDs haben. Das gleiche gilt für die .

+2

Das Problem mit dieser Vorgehensweise ist, dass Sie nicht mehrmals vorher klicken können, nur einmal. Sie müssen entweder ALLE möglichen Erst-in-Seiten manuell indizieren, wenn Sie auf die nächsten Seiten gehen, oder Sie können nur eine Seite zurückgehen und dann haben Sie keinerlei Informationen mehr, um zu einer vorherigen Seite zu gelangen. – for3st

+0

Für diejenigen, die hier stolpern und auch auf das Dilemma von @ for3st stoßen, helfen die natürlichen Eigenschaften eines Arrays, dieses Problem zu beheben. Durch 'push()' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '_id' '' _id'' wird in das Array '_id' geklickt(), wenn Sie vorher klicken. Alles, was Sie tun müssen, ist nur ein Array von ganzen Zahlen. – wootencl

1

Dies ist, was ich mit so weit kam haben - die IDs aller Beiträge zu erhalten, dann die eigentlichen Punkte für die ersten x Anzahl der IDs abrufen ..

Es ist nicht sehr effizient, aber um so mehr als alle Posts abrufen, dann den größten Teil wegwerfen. Zu meiner Überraschung schien es ziemlich schnell zu laufen - ich habe die Methode posthelper.page() 100 Mal ausgeführt und es dauerte ungefähr 0,5 Sekunden.

Ich möchte nicht diese in der eigentlichen Frage stellen, so wäre es nicht die Antworten beeinflussen, wie viel - hier ist der Code:

allPostsUuid = """ 
function(doc) { 
if(doc.type == 'post'){ 
    emit(doc._id, null); 
} 
} 
""" 

class PostsHelper: 
    def __init__(self): 
     server = Server(config.dbhost) 
     db = server[config.dbname] 
     return db 


    def _getPostByUuid(self, uuid): 
     return self.db.get(uuid) 

    def page(self, number = 1): 
     number -= 1 # start at zero offset 
     start = number * config.perPage 
     end = start + config.perPage 

     allUuids = [ 
      x.key for x in self.db.query(allPostsUuid) 
     ] 
     ret = [ 
      self._getPostByUuid(x) for x in allUuids[start : end] 
     ] 

     if len(ret) == 0: 
      raise Error404("Invalid page (%s results)" % (len(allUuids))) 
     else: 
      return ret 
13

Das CouchDB HTTP View API gibt viel Spielraum Paging zu tun effizient . Die einfachste Methode wäre startkey und count. Count ist die maximale Anzahl von Einträgen, die CouchDB für diese Ansichtsanfrage zurückgibt, was Ihrem Design entspricht, und startkey ist der Punkt, an dem CouchDB starten soll. Wenn Sie die Ansicht anfordern, wird Ihnen außerdem angezeigt, wie viele Einträge vorhanden sind. So können Sie berechnen, wie viele Seiten vorhanden sind, wenn Sie dies den Benutzern anzeigen möchten.

Also die erste Anfrage würde keinen Startschlüssel angeben, nur die Anzahl für die Anzahl der Einträge, die Sie anzeigen möchten. Sie können dann den Schlüssel des letzten zurückgegebenen Eintrags notieren und diesen als Startschlüssel für die nächste Seite verwenden. In dieser einfachen Form erhalten Sie eine Überlappung, wobei der letzte Eintrag einer Seite der erste der nächsten ist. Wenn dies nicht erwünscht ist, ist es einfach, den letzten Eintrag der Seite nicht anzuzeigen.

Eine einfachere Methode hierfür ist die Verwendung des Skip-Parameters, um das Startdokument für die Seite zu erstellen. Diese Methode sollte jedoch mit Vorsicht verwendet werden. Der Skip-Parameter bewirkt einfach, dass die interne Engine keine Einträge zurückgibt, über die sie iteriert. Während dies das gewünschte Verhalten ergibt, ist es viel langsamer als das Finden des ersten Dokuments für die Seite nach Schlüssel. Je mehr Dokumente übersprungen werden, desto langsamer wird die Anfrage.

+0

Aha! Von der Seite, die Sie verlinkt haben: Der Parameter count kann mit "skip = Anzahl der zu überspringenden Zeilen" kombiniert werden. Perfekt. – dbr

+0

Ich habe die obigen Informationen zu Ihrer Antwort hinzugefügt (für meine Referenz, wenn nichts anderes), hoffe, es macht Ihnen nichts aus! – dbr

+2

Ich habe es noch einmal bearbeitet. Die Verwendung von Skip ist in den meisten Fällen keine gute Möglichkeit. – Kerr