Paginação: Você (provavelmente) está fazendo tudo errado.

Paginação? Sem problemas! SELECT ... LIMIT X, Y Direito?

Hah! Não exatamente!

Veja, sua lógica de paginação não é estável ; e isso importa um pouco neste mundo ajaxy, client-appy, infinite-scrolly.

TL; DR?

  • Não pagine no deslocamento da linha.
  • Encontre um valor estável para paginar, como a data de um item.
  • Sempre desduplique os itens da lista no lado do cliente.
  • Nunca confie em seu servidor para saber exatamente o que o usuário está olhando.

O quê você está querendo?

Provavelmente é melhor dar um exemplo. Digamos que você esteja adicionando comentários a uma página e queira que os comentários mais recentes apareçam primeiro. A abordagem ingênua é construir uma consulta semelhante a:

SELECT * FROM comments ORDER BY date DESC LIMIT 0, 10

Fácil. Isso dá a você os primeiros 10 comentários mais recentes. Nada de errado aqui. Agora, o usuário vai para baixo e você realiza a mesma consulta, exceto por LIMIT 10, 10– e você retorna os próximos 10 comentários …

…as vezes.

Considere isto:

  • O usuário A está visualizando uma página com os primeiros 10 comentários carregados.
  • O usuário B cria um comentário.
  • O usuário A carrega a próxima página de comentários.

Bem, merda. Agora o usuário A vê um comentário duplicado!

O último comentário da primeira página foi empurrado para baixo pelo novo comentário e se tornou o 11º comentário da lista. Agora sua página parece desleixada ☹

Uma situação semelhante ocorre se você permitir a remoção de itens de uma lista, mas com resultados ainda mais desastrosos .

Em vez de os comentários serem retirados, eles são puxados para cima. O item que anteriormente seria o primeiro na próxima página é deslocado para cima; e o usuário A pularia completamente! Isso é realmente uma merda ☹ ☹

Paginação estável

Não se preocupe, isso geralmente é muito fácil de resolver. Em vez de paginar em um deslocamento volátil (o número da linha), encontre um valor que seja estável ao longo do tempo . No exemplo de comentários, essa é a data dos próprios comentários.

Veja o exemplo acima: Sua primeira consulta é a mesma. No entanto, para a próxima página, em vez de passar o deslocamento da linha, você passa a data do último comentário na lista:

SELECT * FROM comments WHERE date < prevous_date LIMIT 10

Perfeito! Agora você pode ter certeza de que o usuário sempre verá o próximo conjunto de commits que ocorreu após aquele que ele está olhando.

As vezes…

Caveat entroptor

E se você tiver dois comentários com a mesma data? Ack! A paginação é difícil.

Você tem algumas opções:

Se você não tem um ID de incremento automático (por exemplo, a maioria dos armazenamentos de dados distribuídos), as coisas são um pouco mais complicadas:

  • Em vez de encontrar comentários que ocorreram <u> antes </u> da data, encontre comentários que ocorreram <u> em ou antes </u> dessa data. Em seguida, certifique-se de filtrar os comentários duplicados antes de exibi-los para o usuário.

ou:

  • Passe um estado adicional que você pode usar para ignorar os comentários que o usuário já viu (talvez os ids de quaisquer comentários retornados com essa data).

A primeira opção é provavelmente a mais direta, embora exija que uma boa quantidade de dados duplicados voe pela rede.

Isso é ótimo, mas e isso?

Sim. Também há este controle visto com frequência:

[<<] [<] [1] 2 [3] ... [>] [>>]

Como você pula para uma página se estiver paginando com um deslocamento estável como a data do comentário? Você não .

Antes de prosseguir, responda: Com que frequência seus usuários realmente vão para uma página específica diferente de próximo / anterior / primeiro / último?

Eu o desafiaria a evitar um design em que o usuário precise pular para páginas arbitrárias. Existem muitos outros métodos que permitem ao usuário buscar o conteúdo que deseja de forma mais eficaz (a filtragem é a abordagem mais comum).

No entanto, isso levanta algumas outras questões interessantes, não é?

Pule para o fim!

Com esse mundo de paginação, como deixo o usuário pular para o fim? Ack! A paginação é difícil.

Bem, se você tiver que pular para o final de uma lista, uma possibilidade: Inverta sua ordem de classificação e obtenha os primeiros 10 itens na outra direção . Não é tão ruim!

Da mesma forma, como você permite que o usuário volte uma página? Ack! A paginação é muito difícil .

Felizmente, você pode adaptar a abordagem para obter a última página neste caso. Afinal, é apenas uma lista normal que você classifica de uma maneira diferente: pegue a data do item no topo da lista que o usuário está vendo e obtenha a página de itens antes dele! Arrumado!

No entanto, certifique-se de que isso é certo para você. Algumas situações surgem em que você não pode inverter a ordem facilmente e, em seguida, precisa descobrir novas abordagens (pesquisa binária! Chunking! Quem sabe?!?).

Paginação instável

A paginação estável não é uma bala de prata. Considere sites como Reddit e Hacker News . Sua paginação é inerentemente instável : os itens são classificados por uma classificação volátil, freqüentemente movendo para cima e para baixo na lista ao longo do tempo. Como eles lidam com isso? Eles não sabem.

Ambos os sites freqüentemente mostram o quão ruim pode parecer, mostrando itens duplicados conforme você avança as páginas. Não é tão ruim assim, porque nenhum dos sites se inscreve na multidão de rolagem infinita (ainda?).

No entanto, existem muitos aplicativos clientes por aí que apresentam o Reddit e o Hacker News como um feed de rolagem infinita; e alguns deles mostram apenas itens duplicados empilhados uns sobre os outros conforme você rola para baixo. Hora de amador! Tudo o que eles precisam fazer para corrigir essa metade do problema é ignorar itens duplicados ao anexar a próxima página.

Ainda existe a possibilidade de ocultar completamente os itens de você conforme eles caem no ranking. Isso é mais difícil de resolver; o caminho mais direto seria retornar a lista completa para a posição do usuário a cada vez, mas isso é loucura! Provavelmente, é melhor simplesmente ignorar esse caso.