Frage
Wie würde ich über die Umsetzung gehen die Anfragen für Paginierung erforderlich?
Grundsätzlich, wenn Seite 1 angefordert wird, erhalten die ersten 5 Einträge. Für Seite 2, die nächsten 5 bekommen und so weiter.
Ich plane dies über das couchdb-Python-Modul zu verwenden, aber das sollte keinen Unterschied für die Umsetzung machen.
Lösung
Die CouchDB-Führer eine gute Diskussion von Paginierung, darunter viele Beispielcode hier: http://guide.couchdb.org/draft/recipes.html#pagination Hier ist sie Algorithmus:
- Anfrage
rows_per_page + 1
Zeilen aus der Ansicht - Anzeige
rows_per_page
Reihen, speichern letzte Zeile alsnext_startkey
- Wie Seite Informationen, halten
startkey
undnext_startkey
- Verwenden Sie die
next_*
Werte zum nächsten Link zu erstellen, und die anderen verwenden Sie den vorherigen Link erstellen
N. B .: Der richtige Weg, Seiten in CouchDB zu holen ist durch einen Startschlüssel spezifiziert, kein Startindex wie Sie vielleicht denken. Aber wie Sie wissen, was Taste auf der zweiten Seite zu beginnen? Die clevere Lösung: „Stattdessen 10 Zeilen für eine Seite anzufordern, die Sie anfordern 11 Zeilen, aber für die nächste Seite 10 und verwenden Sie die Werte in der 11. Zeile als StartKey Anzeige“
Wenn Sie erwarten, dass mehrere Dokumente emittieren identische Schlüssel haben, müssen Sie startdocid
zusätzlich verwenden, um startkey
richtig Paginieren. Der Grund dafür ist, dass startkey
allein nicht mehr ausreicht, um eine Zeile eindeutig zu identifizieren. Diese Parameter sind nutzlos, wenn Sie nicht über eine startkey
bieten. In der Tat wird CouchDB am startkey
Parameter schaut zuerst, dann wird es die startdocid
Parameter nutzen, um den Beginn des Bereichs neu zu definieren, wenn mehrere potenziellen staring Reihen den gleichen Schlüssel, aber verschiedenen Dokument-IDs haben. Das Gleiche gilt für die enddocid
.
Andere Tipps
Das CouchDB HTTP Ansicht API viel Spielraum gibt effizient Paging zu tun.
Die einfachste Methode wäre startkey
und count
verwenden. Count ist die maximale Anzahl der Einträge CouchDB für diese Ansicht Anfrage zurück, etwas, das bis zu Ihrem Design, und StartKey ist, wo Sie wollen CouchDB starten. Wenn Sie die Ansicht fordern wird es auch Ihnen sagen, wie viele Einträge gibt es, so dass Sie berechnen, wie viele Seiten wird es sein, wenn Sie, dass für die Benutzer angezeigt werden sollen.
Der erste Antrag würde keine StartKey angeben, nur die Anzahl für die Anzahl der Einträge, die Sie zeigen möchten. Sie können dann beachten Sie die Taste des letzten Eintrags zurückgegeben und dass für die nächste Seite als Start-Taste verwenden. In dieser einfachen Form, erhalten Sie eine Überlappung erhalten, wo der letzte Eintrag einer Seite der ersten der nächsten ist. Ist dies nicht erwünscht ist, ist es trivial einfach nicht den letzten Eintrag auf der Seite angezeigt werden soll.
Eine einfachere Methode, dies zu tun ist, um die Parameter skip zu verwenden, um das Startdokument für die Seite zu erarbeiten, aber diese Methode sollte mit Vorsicht angewandt werden. Der Sprung-Parameter bewirkt, dass einfach der interne Motor nicht Einträge zurück, die es iterieren. Während dies das gewünschte Verhalten gibt, ist es viel langsamer als das erste Dokument für die Seite durch Schlüssel zu finden. Je mehr Dokumente, die übersprungen werden, desto langsamer wird die Anforderung sein.
Das ist, was ich kam haben mit so weit nach oben - die IDs aller Beiträge zu bekommen, dann rufen Sie die tatsächlichen Elemente für die erste x Anzahl der IDs ..
Es ist nicht sehr effizient, aber um so mehr, als alle Beiträge abrufen, dann die meisten der wegzuwerfen. Das heißt, zu meiner Überraschung, schien es ziemlich schnell zu laufen -. Ich die posthelper.page()
Methode 100 Mal lief und es dauerte etwa 0,5 Sekunden
Das habe ich nicht in der eigentlichen Frage zu stellen, so wäre es die Antworten nicht so viel Einfluss - 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
-
Hier unten ist die rekursive Art, wie ich gefunden:
zwei Variablen nehmen
var lastOffset = 0; var counter = 0;
function someRecursive(lastOffset,counter) {
queryView(db, whereClause).then(result => {
var rows_per_page = 5;
//formula below
var page = Math.floor((lastOffset == 0 ? 0: (result.offset - lastOffset) +
(rows_per_page * counter)) / rows_per_page) + 1;
var skip = page * rows_per_page;
if (somerecursionexitcondition) {
counter = lastOffset == 0 ? lastOffset: counter + 1;
lastOffset =result.offset;
someRecursive(lastOffset, counter).then(result => {
resolve();
});
});
}