web-dev-qa-db-fra.com

Comment implémenter des curseurs pour la pagination dans une API

Ceci est similaire à cette question qui n'a pas de réponses. J'ai tout lu sur la façon d'utiliser les curseurs avec les Twitter , facebook , et disqus api et aussi cet article = sur la façon dont Disqus a généralement construit ses curseurs, mais je n'arrive toujours pas à comprendre le concept de la façon dont ils fonctionnent et comment implémenter une solution similaire dans mes propres projets. Quelqu'un peut-il expliquer spécifiquement les différentes techniques et concepts qui les sous-tendent?

42
Micah

Permet d'abord de comprendre pourquoi la pagination de décalage échoue pour les grands ensembles de données avec un exemple.

Les clients fournissent deux paramètres limite pour le nombre de résultats et offset et pour le décalage de page. Par exemple, avec offset = 40, limit = 20, nous pouvons dire à la base de données de renvoyer les 20 éléments suivants, en sautant les 40 premiers.

Inconvénients:

  • L'utilisation de LIMIT OFFSET n'est pas adaptée aux grands ensembles de données . Comme l'offset augmente au fur et à mesure que vous avancez dans l'ensemble de données, la base de données doit toujours lire jusqu'à offset + compter les lignes du disque , avant de supprimer l'offset et renvoyant uniquement le nombre de lignes.
  • Si des éléments sont écrits dans le jeu de données à une fréquence élevée, la fenêtre de page devient peu fiable, sautant ou renvoyant potentiellement des résultats en double .

Comment les curseurs résolvent-ils cela?

La pagination basée sur le curseur fonctionne en en renvoyant un pointeur sur un élément spécifique dans l'ensemble de données . Lors des requêtes suivantes, le serveur renvoie les résultats après le pointeur donné.

Nous utiliserons les paramètres next_cursor avec limit comme paramètres fournis par le client dans ce cas.

Supposons que nous voulions paginer de l'utilisateur le plus récent à l'utilisateur le plus âgé. Lors de la première demande du client, supposons que nous sélectionnions la première page via la requête:

SELECT * FROM users
WHERE team_id = %team_id
ORDER BY id DESC
LIMIT %limit

limite est égal à limite plus un , pour récupérer un résultat de plus que le nombre spécifié par le client. Le résultat supplémentaire n'est pas renvoyé dans le jeu de résultats, mais nous utilisons l'ID de la valeur comme next_cursor .

La réponse du serveur serait:

{
   "users": [...],
   "next_cursor": "1234",  # the user id of the extra result
}

Le client fournirait alors next_cursor comme curseur dans la deuxième requête.

SELECT * FROM users
WHERE team_id = %team_id
AND id <= %cursor
ORDER BY id DESC
LIMIT %limit

Avec cela, nous avons résolu les inconvénients de la pagination basée sur le décalage:

  • Au lieu que la fenêtre soit calculée à partir de zéro à chaque demande en fonction du nombre total d'articles, nous récupérons toujours les prochaines lignes de comptage après un point de référence spécifique . Si des éléments sont écrits dans le jeu de données à une fréquence élevée, la position globale du curseur dans l'ensemble peut changer, mais la fenêtre de pagination s'ajuste en conséquence.
  • Cela s'adaptera bien aux grands ensembles de données. Nous utilisons une clause WHERE pour récupérer des lignes dont les valeurs d'ID sont inférieures au dernier identifiant de la page précédente. Cela nous permet de tirer parti de l'index sur la colonne et la base de données n'a pas à lire les lignes que nous avons déjà vues .

Pour une explication détaillée, vous pouvez visiter ce merveilleux article d'ingénierie de mou!

53

En général, vous devez transmettre l'élément ou le numéro de page actuel dans la demande en tant que paramètre. Un autre paramètre habituel est la taille du lot de la page. Ensuite, côté serveur, vous sélectionnez et renvoyez l'ensemble de données approprié, avec une requête SQL par exemple.

1
Ho Zong

Voici un article sur la pagination: pagination-en temps réel-pagination basée sur le curseur de données

Curseurs - nous devons avoir au moins une colonne avec des valeurs séquentielles uniques pour implémenter la pagination basée sur le curseur. Cela peut être similaire au paramètre max_id de Twitter ou au paramètre after de Facebook.

1
Goo Hong