Pregunta

¿Cómo haría para implementar las consultas requeridas para la paginación?

Básicamente, cuando se solicita la página 1, obtenga las primeras 5 entradas. Para la página 2, obtenga los siguientes 5 y así sucesivamente.

Planeo usar esto a través del módulo couchdb-python, pero eso no debería hacer ninguna diferencia en la implementación.

¿Fue útil?

Solución

La Guía CouchDB tiene una buena discusión sobre la paginación, incluidos muchos códigos de muestra, aquí: http://guide.couchdb.org/draft/recipes.html#pagination Aquí está su algoritmo:

  • Solicite rows_per_page + 1 filas de la vista
  • Mostrar rows_per_page filas, almacenar la última fila como next_startkey
  • Como información de la página, mantenga startkey y next_startkey
  • Use los valores next_ * para crear el siguiente enlace, y use los otros para crear el enlace anterior

N.B .: La forma correcta de recuperar páginas en CouchDB es especificando una clave de inicio, no un índice de inicio como podría pensar. Pero, ¿cómo sabes en qué tecla comenzar la segunda página? La solución inteligente: " En lugar de solicitar 10 filas para una página, solicita 11 filas, pero muestra solo 10 y usa los valores en la 11ª fila como la tecla de inicio para la página siguiente. & Quot;

Si espera que varios documentos emitan claves idénticas, deberá usar startdocid además de startkey para paginar correctamente. La razón es que startkey solo ya no será suficiente para identificar de forma exclusiva una fila. Esos parámetros son inútiles si no proporciona una startkey . De hecho, CouchDB primero mirará el parámetro startkey , luego usará el parámetro startdocid para redefinir aún más el comienzo del rango si múltiples filas de mira potenciales tienen la misma clave pero diferentes ID de documentos. Lo mismo para el enddocid .

Otros consejos

El CouchDB HTTP View API ofrece un amplio margen para realizar la paginación de manera eficiente.

El método más simple usaría startkey y count . El recuento es el número máximo de entradas que CouchDB devolverá para esa solicitud de vista, algo que depende de su diseño, y la tecla de inicio es donde desea que comience CouchDB. Cuando solicite la vista, también le indicará cuántas entradas hay, lo que le permite calcular cuántas páginas habrá si desea mostrarlas a los usuarios.

Entonces, la primera solicitud no especificaría una tecla de inicio, solo el recuento de la cantidad de entradas que desea mostrar. Luego puede anotar la clave de la última entrada devuelta y usarla como clave de inicio para la página siguiente. En esta forma simple, obtendrá una superposición, donde la última entrada de una página es la primera de la siguiente. Si esto no es deseable, es trivial simplemente no mostrar la última entrada de la página.

Un método más simple para hacerlo es usar el parámetro skip para elaborar el documento de inicio de la página, sin embargo, este método debe usarse con precaución. El parámetro de omisión simplemente hace que el motor interno no devuelva entradas sobre las que está iterando. Si bien esto proporciona el comportamiento deseado, es mucho más lento que encontrar el primer documento para la página por clave. Cuantos más documentos se omitan, más lenta será la solicitud.

Esto es lo que se me ocurrió hasta ahora: para obtener los identificadores de todas las publicaciones, luego recuperar los elementos reales para el primer número x de ID ...

No es terriblemente eficiente, pero más que recuperar todas las publicaciones y luego tirar la mayor parte de la basura. Dicho esto, para mi sorpresa, parecía funcionar bastante rápido: ejecuté el método posthelper.page () 100 veces y me tomó aproximadamente 0.5 segundos.

No quería publicar esto en la pregunta real, por lo que no influiría tanto en las respuestas: aquí está el código:

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
  • Aquí abajo está la forma recursiva que encontré:

    Toma dos variables

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

                           });
  });

  }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top