Domanda

Come potrei fare per implementare le query richieste per l'impaginazione?

Fondamentalmente, quando è richiesta la pagina 1, ottieni le prime 5 voci. Per pagina 2, ottieni i prossimi 5 e così via.

Ho intenzione di usarlo tramite il modulo couchdb-python, ma ciò non dovrebbe fare alcuna differenza per l'implementazione.

È stato utile?

Soluzione

La Guida CouchDB ha una buona discussione sulla paginazione, incluso un sacco di codice di esempio, qui: http://guide.couchdb.org/draft/recipes.html#pagination Ecco il loro algoritmo:

  • Richiedi rows_per_page + 1 righe dalla vista
  • Visualizza righe_per_pagina , archivia l'ultima riga come next_startkey
  • Come informazioni sulla pagina, tieni startkey e next_startkey
  • Utilizza i valori next_ * per creare il link successivo e usa gli altri per creare il link precedente

N.B .: Il modo corretto di recuperare le pagine in CouchDB è specificare una chiave di partenza, non un indice di partenza come si potrebbe pensare. Ma come fai a sapere su quale chiave avviare la seconda pagina? La soluzione intelligente: " Invece di richiedere 10 righe per una pagina, richiedi 11 righe, ma visualizzi solo 10 e usi i valori nell'undicesima riga come chiave di avvio per la pagina successiva. & Quot;

Se si prevede che più documenti emettano chiavi identiche, è necessario utilizzare startdocid oltre a startkey per impaginare correttamente. Il motivo è che startkey da solo non sarà più sufficiente per identificare in modo univoco una riga. Tali parametri sono inutili se non si fornisce un startkey . In effetti, CouchDB esaminerà prima il parametro startkey , quindi utilizzerà il parametro startdocid per ridefinire ulteriormente l'inizio dell'intervallo se più potenziali righe fisse hanno la stessa chiave ma ID documento diversi. Stessa cosa per enddocid .

Altri suggerimenti

CouchDB API di visualizzazione HTTP offre molte possibilità di eseguire il paging in modo efficiente.

Il metodo più semplice utilizza startkey e count . Count è il numero massimo di voci che CouchDB restituirà per quella richiesta di visualizzazione, qualcosa che dipende dal tuo design, e la chiave di avvio è dove vuoi che CouchDB inizi. Quando richiedi la visualizzazione, ti dirà anche quante voci ci sono, permettendoti di calcolare quante pagine ci saranno se vuoi mostrarle agli utenti.

Quindi la prima richiesta non specifica una chiave di avvio, ma solo il conteggio del numero di voci che vuoi mostrare. È quindi possibile annotare la chiave dell'ultima voce restituita e utilizzarla come chiave di avvio per la pagina successiva. In questo semplice modulo, otterrai una sovrapposizione, in cui l'ultima voce di una pagina è la prima della successiva. Se ciò non è desiderabile, è banale semplicemente non visualizzare l'ultima voce della pagina.

Un metodo più semplice per farlo è usare il parametro skip per elaborare il documento iniziale per la pagina, tuttavia questo metodo dovrebbe essere usato con cautela. Il parametro skip fa semplicemente in modo che il motore interno non restituisca le voci su cui sta ripetendo. Sebbene ciò dia il comportamento desiderato, è molto più lento rispetto alla ricerca del primo documento per la pagina. Più documenti vengono ignorati, più lenta sarà la richiesta.

Questo è quello che ho escogitato finora: ottenere gli ID di tutti i post, quindi recuperare gli elementi effettivi per il primo x numero di ID ..

Non è terribilmente efficiente, ma più che recuperare tutti i post, quindi buttare via la maggior parte. Detto questo, con mia sorpresa, sembrava funzionare abbastanza velocemente - ho eseguito il metodo posthelper.page () 100 volte e ci sono voluti circa 0,5 secondi.

Non volevo pubblicare questo nella domanda reale, quindi non influenzerebbe altrettanto le risposte - ecco il codice:

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
  • Di seguito è riportato il modo ricorsivo che ho trovato:

    Prendi due variabili

  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();

                           });
  });

  }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top