[RAILS] So implementieren Sie Paginierung in GraphQL (für Ruby)

Hintergrund

In Carely von unserem Service wird die Serverseite von Ruby (on Rails) implementiert, und der Datenaustausch mit der Front (Vue) wird von graphQL implementiert. Bei der Paginierung in Schienen wird häufig ein Juwel namens Kaminari verwendet. Bei graphQL scheint die Cursor-Paginierung im Relay-Stil Standard zu sein, daher habe ich beide Implementierungsmethoden ausprobiert.

Über das Juwel und die Version, die Sie verwenden (Stand 26. Juni 2020)

kaminari ist Version 1.2.1 graphql-ruby ist Version 1.10.10 ist.

Implementierung mit Relay-Style-Cursor-Paginierung

(Dies ist die URL zur Erläuterung der Paginierung von graphql-ruby) https://graphql-ruby.org/pagination/using_connections.html

Beispiel für eine serverseitige Implementierung

Beschreiben Sie die Schema-Klasse für die Verwendung des Paginierungs-Plugins wie unten gezeigt.


class MySchema < GraphQL::Schema
  .
  .
  use GraphQL::Pagination::Connections
  .
end

Verwenden Sie die Beschreibung :: connection_type, um die Abfrage zu definieren, zu der Sie die Paginierungsfunktion hinzufügen möchten.

field :users, Types::UserType::connection_type, null: true do
  .
  .
  argument :name, String, "Name", required: false
  .
end

Das ist alles für die serverseitige Implementierung.

Beispiel für einen Front-Side-Abfrageaufruf

Sie können jetzt die Parameter für "first (last), after (before)" angeben. Mit der folgenden Abfrage werden 10 Elemente von zuerst und 10 Elemente von nachher durch Angabe von nachher erfasst. Geben Sie für die nachfolgend angegebene Zeichenfolge die vom Cursor erhaltene Zeichenfolge an. Es kann auch ein Feld mit dem Namen "pageInfo" angegeben werden. Gibt es eine vorherige oder eine nächste Seite? Sie können die Position der Start- und Endcursor ermitteln.


query MyQuery {
  users (first: 10, after: "xxxx") {
    pageInfo {
      hasPreviousPage  
      hasNextPage
      endCursor
      startCursor
    }
   edges {
     cursor
        node {
          firstName
          lastName
          mailAddress
          age
          .
          .
        }
      }
   ##Kann mit Knoten genommen werden
   nodes {
     firstName
     lastName
     mailAddress
     age
     .
     .
   }


##Beispiel Ergebnis
{
  "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"
       },
        .
        .
     ]

Implementierung mit Kaminari

Die allgemeinen Methoden für die Paginierung in Kaminari sind wie folgt.

#Teilen Sie die erste Seite alle 10
User.page(1).per(10)
#Gesamtzahl
User.page(1).per(10).total_count
#Anzahl der Tolal-Seiten
User.page(1).total_pages
#Anzahl der Seiten pro Seite
User.page(1).limit_value
#Aktuelle Anzahl der Seiten
User.page(1).current_page
#Nächste Seitenzahl
User.page(1).next_page
#Anzahl der vorherigen Seiten
User.page(1).prev_page
#Ob es die erste Seite ist
User.page(1).first_page?
#Ob es die letzte Seite ist
User.page(1).last_page?

Implementierungsbeispiel bei Verwendung der Kaminari-Funktion mit GraphQL

Erstellen Sie einen Typ für die Paginierung wie unten gezeigt.


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

Erstellen Sie einen "UserType" und einen "UsersType", die mehrere Benutzerinformationen und eine Paginierung wie folgt zurückgeben:


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


Fügen Sie der Abfrage die folgende Verarbeitung hinzu, um Paginierungsinformationen zurückzugeben.


#Seite mit Argument,Hinzugefügt, um per bestehen zu können
field :users, Types::UserType, null: true do
  .
  .
  argument :name, String, "Name", required: false
  argument :page, Int, required: false
  argument :per, Int, required: false
  .
end

#Verwenden Sie die Paginierung von kaminari, wenn es Argumente Seite und per gibt
def users(**args)
  .
  .
  users = User.page(args[:page]).per(args[:per])
  {
     users: users,
     pagination: pagination(users)
  }
end

#Gibt die Nummer nach der Kaminari-Methode zurück
def pagination(result)
  {
    total_count: result.total_count,
    limit_value: result.limit_value,
    total_pages: result.total_pages,
    current_page: result.current_page
  }
end

Dies ist ein Beispiel für eine Abfrage, bei der die erste Seite, die in 10 Fälle unterteilt ist, und das Ergebnis abgerufen werden.


query MyQuery {
  users (per:10, page:1) {
    pagination {
      currentPage
      limitValue
      totalCount
      totalPages
    }
   users {
     firstName
     lastName
     mailAddress
     age
     .
     .
   }
}
   

##Beispiel Ergebnis
{
  "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"
        },
        .
        .
     ]

Über den richtigen Gebrauch

Relay-Style Cursor Pagination Es sieht gut aus, weil es einfach zu bedienen ist, wenn Sie nur mit der API nach Informationen suchen. Wenn Sie eine Benutzeroberfläche erstellen möchten, die die Gesamtzahl der Fälle und die Gesamtzahl der Seiten auf der Vorderseite anzeigt, da sie nur die Standortinformationen per Cursor enthält, Benutzerdefiniert ) Scheint eine "Verbindung" herstellen zu müssen.

kaminari Wenn Sie nur interne Ingenieure verwenden und eine Benutzeroberfläche erstellen, die die Gesamtzahl der Fälle und die Gesamtzahl der Seiten auf der Vorderseite anzeigt, ist die Verwendung von Kaminari weniger arbeitsintensiv.

Persönlich denke ich, dass es besser wäre, eine benutzerdefinierte Verbindung mit "Relay-Style Cursor Pagination" zu erstellen, da dies dem Stil von graphQL entspricht.

Recommended Posts

So implementieren Sie Paginierung in GraphQL (für Ruby)
Wie man in Ruby auf unbestimmte Zeit iteriert
Versuchen Sie, Yuma in Ruby zu implementieren
So installieren Sie Bootstrap in Ruby
So implementieren Sie Suchfunktionen in Rails
So implementieren Sie den Kalman-Filter mit Java
[Ruby] Wie man Slice für Anfänger benutzt
So implementieren Sie Ranking-Funktionen in Rails
So implementieren Sie die asynchrone Verarbeitung in Outsystems
[Für Anfänger] So debuggen Sie mit Eclipse
So erstellen Sie eine Abfrage mithilfe von Variablen in GraphQL [Verwenden von Ruby on Rails]
So erstellen Sie Pagenationen für das "Kaminari" -Array
[Rails] So implementieren Sie einen Unit-Test eines Modells
[Für Anfänger] So implementieren Sie die Löschfunktion
So implementieren Sie eine ähnliche Funktion in Rails
So implementieren Sie optimistisches Sperren in der REST-API
So erstellen Sie die einfachste Blockchain in Ruby
So implementieren Sie UICollectionView mit Code nur in Swift
[Ruby] Verwendung der Standardausgabe bei der bedingten Verzweigung
So implementieren Sie die Gastanmeldung in 5 Minuten im Rails-Portfolio
So implementieren Sie eine nette Funktion in Ajax mit Rails
[Ruby on Rails] Wie schreibe ich eine Enumeration auf Japanisch?
Rails / Ruby: So erhalten Sie HTML-Text für Mail
[Ruby On Rails] So setzen Sie die Datenbank in Heroku zurück
So starten Sie einen anderen Befehl in einem Ruby-Programm
Umgang mit TSV-Dateien und CSV-Dateien in Ruby
Zusammenfassung der Implementierung von Standardargumenten in Java
So beheben Sie den SSL_connect-Fehler im PayPal Ruby SDK
Verwendung von Ruby return
Ruby: Wie man Cookies benutzt
[Rails] So implementieren Sie Scraping
[Java] So implementieren Sie Multithreading
[Ruby on Rails] So implementieren Sie die Tagging- / inkrementelle Suchfunktion für Posts (ohne Gem)
[Ruby] So teilen Sie jede GraphQL-Abfrage in Dateien auf
So ändern Sie eine Zeichenfolge in einem Array in eine Zahl in Ruby
So rufen Sie den Hashwert in einem Array in Ruby ab
So zeigen Sie Diagramme in Ruby on Rails an (LazyHighChart)
So implementieren Sie eine einzeilige Anzeige von TextView in der Android-Entwicklung
So installieren Sie die Webanwendung für jede Sprache in Nginx
Wie man Lombok im Frühling benutzt
So legen Sie die Validierung für time_field fest
So führen Sie JUnit in Eclipse aus
So installieren Sie JMeter für Mac
Wie man Ant in Gradle ausführt
Wie man die Programmierung in 3 Monaten beherrscht
So installieren Sie Ruby über rbenv
Wie man JAVA in 7 Tagen lernt
So erhalten Sie Parameter in Spark
Implementieren Sie den gRPC-Client in Ruby
So installieren Sie jQuery in Rails 6