Dans Carely, notre service, le côté serveur est implémenté en Ruby (on Rails), et l'échange de données avec le front (Vue) est implémenté en graphQL. La pagination dans Rails utilise souvent une gemme appelée Kaminari, mais dans le cas de graphQL, la pagination du curseur de style relais semble être standard, j'ai donc essayé les deux méthodes d'implémentation.
kaminari est la version 1.2.1 graphql-ruby est la version 1.10.10 est.
(Ceci est l'URL pour expliquer la pagination de graphql-ruby) https://graphql-ruby.org/pagination/using_connections.html
Décrivez la classe de schéma pour utiliser le plugin de pagination comme indiqué ci-dessous.
class MySchema < GraphQL::Schema
  .
  .
  use GraphQL::Pagination::Connections
  .
end
Utilisez la description :: connection_type pour définir la requête à laquelle vous souhaitez ajouter la fonctionnalité de pagination.
field :users, Types::UserType::connection_type, null: true do
  .
  .
  argument :name, String, "Nom", required: false
  .
end
C'est tout pour l'implémentation côté serveur.
Vous pouvez maintenant spécifier les paramètres pour premier (dernier), après (avant).
Avec la requête ci-dessous, 10 éléments seront acquis à partir du premier et 10 éléments seront acquis par après en spécifiant après.
Pour la chaîne de caractères spécifiée dans after, spécifiez la chaîne de caractères obtenue par le curseur.
De plus, un champ appelé «pageInfo» peut être spécifié, et y a-t-il une page précédente ou une page suivante? Vous pouvez obtenir la position des curseurs de début et de fin.
query MyQuery {
  users (first: 10, after: "xxxx") {
    pageInfo {
      hasPreviousPage  
      hasNextPage
      endCursor
      startCursor
    }
   edges {
     cursor
        node {
          firstName
          lastName
          mailAddress
          age
          .
          .
        }
      }
   ##Peut être pris avec des nœuds
   nodes {
     firstName
     lastName
     mailAddress
     age
     .
     .
   }
##Exemple de résultat
{
  "data": {
    "users": {
      "pageInfo": {
        "hasPreviousPage": false,
        "hasNextPage": true,
        "endCursor": "MTA",
        "startCursor": "MQ"
      },
      "edges": [
        {
          "cursor": "MQ",
          "node": {
            "firstName": "Hogehoge",
            "lastName": "Fuga Fuga",
            "mailAddress": "[email protected]",
            "age": "20"
          }
        },
        {
          "cursor": "Mg",
          "node": {
            "firstName": "Hogehoge 2",
            "lastName": "Fuga Fuga 2",
            "mailAddress": "[email protected]",
            "age": "30"
          }
        },
        .
        .
     ],
     "nodes": [
       {
         "firstName": "Hogehoge",
         "lastName": "Fuga Fuga",
         "mailAddress": "[email protected]",
         "age": "20"
       },
       {
         "firstName": "Hogehoge 2",
         "lastName": "Fuga Fuga 2",
         "mailAddress": "[email protected]",
         "age": "30"
       },
        .
        .
     ]
Les méthodes générales utilisées pour la pagination en kaminari sont les suivantes.
#Obtenez la première page divisée tous les 10
User.page(1).per(10)
#nombre total
User.page(1).per(10).total_count
#nombre de pages tolal
User.page(1).total_pages
#Nombre de pages par page
User.page(1).limit_value
#Nombre actuel de pages
User.page(1).current_page
#Nombre de pages suivantes
User.page(1).next_page
#Nombre de pages précédentes
User.page(1).prev_page
#Que ce soit la première page
User.page(1).first_page?
#Que ce soit la dernière page
User.page(1).last_page?
Créez un type pour la pagination comme indiqué ci-dessous.
module Types
  class PaginationType < Types::BaseObject
    field :total_count, Int, null: true
    field :limit_value, Int, null: true
    field :total_pages, Int, null: true
    field :current_page, Int, null: true
  end
end
Créez un ʻUserType et un ʻUsersType qui renvoie plusieurs informations utilisateur et une pagination comme suit:
module Types
  class UserType < Types::BaseObject
    field :uuid, String, null: true
    field :first_name, String, null: true
    field :last_name, String, null: true
    field :mail_address, String, null: true
    field :age, String, null: true
    .
    .
  end
end
module Types
  class UsersType < Types::BaseObject
    field :pagination, PaginationType, null: true
    field :users, [UserType], null: true
  end
end
Ajoutez le traitement suivant à Query pour renvoyer les informations de pagination.
#Page avec argument,Ajouté pour pouvoir passer par
field :users, Types::UserType, null: true do
  .
  .
  argument :name, String, "Nom", required: false
  argument :page, Int, required: false
  argument :per, Int, required: false
  .
end
#Utilisez la pagination de kaminari s'il y a une page d'arguments et par
def users(**args)
  .
  .
  users = User.page(args[:page]).per(args[:per])
  {
     users: users,
     pagination: pagination(users)
  }
end
#Renvoie le nombre en utilisant la méthode de Kaminari
def pagination(result)
  {
    total_count: result.total_count,
    limit_value: result.limit_value,
    total_pages: result.total_pages,
    current_page: result.current_page
  }
end
Voici un exemple de requête qui récupère la première page divisée en 10 cas et le résultat.
query MyQuery {
  users (per:10, page:1) {
    pagination {
      currentPage
      limitValue
      totalCount
      totalPages
    }
   users {
     firstName
     lastName
     mailAddress
     age
     .
     .
   }
}
   
##Exemple de résultat
{
  "data": {
    "users": {
      "pagination": {
        "currentPage": 1,
        "limitValue": 10,
        "totalCount": 100,
        "totalPages": 10
      },
      "users": [
        {
          "firstName": "Hogehoge",
          "lastName": "Fuga Fuga",
          "mailAddress": "[email protected]",
          "age": "20"
        },
        {
          "firstName": "Hogehoge 2",
          "lastName": "Fuga Fuga 2",
          "mailAddress": "[email protected]",
          "age": "30"
        },
        .
        .
     ]
Relay-Style Cursor Pagination
Cela a l'air bien car il est facile à utiliser si vous recherchez simplement des informations avec l'API.
Si vous souhaitez créer une interface utilisateur qui affiche le nombre total de cas et le nombre total de pages au recto car elle ne contient que les informations de localisation par curseur, Personnalisé ) Semble avoir besoin de créer une connexion.
kaminari
Si vous n'utilisez que des ingénieurs internes et créez une interface utilisateur qui affiche le nombre total de cas et le nombre total de pages au recto, l'utilisation de kaminari demande moins de travail.
Personnellement, je pense qu'il serait préférable de créer une connexion personnalisée en utilisant Relay-Style Cursor Pagination car cela convient au style de graphQL.
Recommended Posts