Pergunta
Como eu iria sobre a implementação das consultas necessárias para a paginação?
Basicamente, quando página 1 é solicitada, obtenha as primeiras 5 entradas. Por página 2, obter o próximo 5 e assim por diante.
Eu pretendo usar isso através do módulo couchdb-python, mas que não deve fazer qualquer diferença para a implementação.
Solução
O Guia CouchDB tem uma boa discussão de paginação, incluindo os lotes de código de exemplo, aqui: http://guide.couchdb.org/draft/recipes.html#pagination Aqui está seu algoritmo:
- linhas Pedido
rows_per_page + 1
da vista ??li> - linhas de exibição
rows_per_page
, armazenar última linha comonext_startkey
- Como a informação da página, mantenha
startkey
enext_startkey
- Use os valores
next_*
para criar o próximo link, e usar os outros para criar o link anterior
NB .: A maneira correta para buscar páginas na CouchDB é especificando uma chave de partida, não um índice começando como você poderia pensar. Mas como você sabe o que tecla para iniciar a 2ª página em? A solução inteligente: "Em vez de solicitar 10 linhas para uma página, você solicitar 11 linhas, mas exibir apenas 10 e usar os valores na linha 11 como o StartKey para a próxima página"
Se você espera ter vários documentos emitem chaves idênticas, você vai precisar usar startdocid
além startkey
para paginar corretamente. A razão é que startkey
por si só, não ser suficiente para identificar unicamente uma linha. Esses parâmetros são inúteis se você não fornecer um startkey
. Na verdade, CouchDB vai olhar primeiro para o parâmetro startkey
, então ele vai usar o parâmetro startdocid
para mais redefinir o início do intervalo se várias linhas possíveis de olhar fixamente ter a mesma chave, mas diferentes IDs de documentos. Mesma coisa para o enddocid
.
Outras dicas
O CouchDB HTTP Ver API dá muita margem para fazer paginação de forma eficiente.
O método mais simples seria usar startkey
e count
. Count é o número máximo de entradas CouchDB irá retornar para essa solicitação vista, algo que é até o seu design, e StartKey é onde você quer CouchDB para começar. Quando você solicita o ponto de vista que também irá dizer-lhe quantas entradas existem, o que lhe permite calcular quantas páginas haverá se você quiser mostrar que para os usuários.
Assim, o primeiro pedido não especificar um StartKey, apenas a contagem para o número de entradas que deseja mostrar. Você pode em seguida, anote a chave da última entrada retornou e usar isso como a chave de ignição para a próxima página. Nesta forma simples, você vai ter uma sobreposição, onde a última entrada de uma página é o primeiro do próximo. Se isso não é desejável é trivial simplesmente não exibir a última entrada da página.
Um método mais simples de fazer isso é usar o parâmetro de salto para trabalhar fora do documento inicial para a página, no entanto, este método deve ser usado com cautela. O parâmetro de ignorar simplesmente faz com que o motor interno para não retornar entradas que ele está interagindo sobre. Enquanto isso dá o comportamento desejado é muito mais lento do que encontrar o primeiro documento para a página por chave. Os mais documentos que são ignorados, o mais lento o pedido será.
Este é o que eu vim com até agora - para obter os IDs de todos os lugares, em seguida, recuperar os itens reais para o primeiro número x de IDs ..
Não é terrivelmente eficiente, mas mais do que recuperar todas as mensagens, em seguida, jogando a maior parte da distância. Dito isto, para minha surpresa, ele parecia correr muito rapidamente -. Corri o método posthelper.page()
100 vezes e levou cerca de 0,5 segundos
Eu não queria postar isso na questão real, por isso não influenciaria as respostas como muito - aqui está o 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
-
Aqui abaixo é a maneira recursiva eu ??encontrei:
Tome duas variáveis ??
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();
});
});
}