Implementing the Relay Connection Specification
We naively implemented cursor based pagination in the previous tutorial . To ensure a consistent implementation of this pattern, the Relay project has a formal specification you can follow for building GraphQL APIs which use a cursor based connection pattern.
By the end of this tutorial, we should be able to return a connection of users when requested.
Connections
A Connection represents a paginated relationship between two entities. This pattern is used when the relationship itself has attributes. For example, we might have a connection of users to represent a paginated list of users.
Let us define a Connection type which takes in a Generic ObjectType.
Connections must have atleast two fields: edges
and page_info
.
The page_info
field contains metadata about the connection. Following the
Relay specification, we can define a PageInfo
type like this:
You can read more about the PageInfo
type at:
- https://graphql.org/learn/pagination/#pagination-and-edges
- https://relay.dev/graphql/connections.htm
The edges
field must return a list type that wraps an edge type.
Following the Relay specification, let us define an Edge that takes in a generic ObjectType.
EdgeTypes must have atleast two fields - cursor
and node
. Each edge has itβs
own cursor and item (represented by the node
field).
Now that we have the types needed to implement pagination using Relay Connections, let us use them to paginate a list of users. For simplicityβs sake, let our dataset be a list of dictionaries.
Now is a good time to think of what we could use as a cursor for our dataset. Our cursor needs to be an opaque value, which doesnβt usually change over time. It makes sense to use base64 encoded IDs of users as our cursor, as they fit both criteria.
While working with Connections, it is a convention to base64-encode cursors. It provides a unified interface to the end user. API clients need not bother about the type of data to paginate, and can pass unique IDs during pagination. It also makes the cursors opaque.
Let us define a couple of helper functions to encode and decode cursors as follows:
Let us define a get_users
field which returns a connection of users, as well
as an UserType
. Let us also plug our query into a schema.
you can start the debug server with the following command:
Hereβs an example query to try out: