23
GraphQL Design Pattern (1): Pagination & Summary
So I designed a schema for a common feature,
basically frontend needs to display two things:
basically frontend needs to display two things:
Suppose the page is about showing a list of
animals, and we want to show them the summary of
each type of animals.
animals, and we want to show them the summary of
each type of animals.
FILTERS
[ ] Mammal (200)
[x] Birds (110)
[ ] Fish (200)
ITEMS
- Eagle
- Pigeon
- Stork
- ...
Initially, the schema I designed is as follows:
query {
displayAnimals(animalTypes: [AnimalType!]!): DisplayAnimalsResult!
}
enum AnimalType {
MAMMAL
BIRD
FISH
}
type DisplayAnimalsResult {
summary: DisplayAnimalsResultSummary!
animals: FilteredAnimals!
}
type DisplayAnimalsResultSummary {
mammal: Int!
bird: Int!
fish: Int!
}
type FilteredAnimals {
totalCount: Int!
paginate(pagingOptions: PagingOptions!): [Animal!]!
}
type PagingOptions {
currentPage: Int!
itemsPerPage: Int!
}
type Animal {
name: String!
}
And the frontend query:
query DisplayAnimal(
$animalTypes: [AnimalType!]!
$pagingOptions: PagingOptions!
) {
displayAnimals(animalTypes: $animalTypes) {
summary {
mammal
bird
fish
}
animals {
totalCount
paginate(pagingOptions: $pagingOptions) {
name
}
}
}
}
summary
property feels like a boilerplate to implement.After seeing this pattern over and over and getting
frustrated, I suddenly realised that the
property is actually not needed!
frustrated, I suddenly realised that the
summary
property is actually not needed!
Let's see the new schema (note that
DisplayAnimalsResult
and DisplayAnimalsResultSummary
are gone):query {
displayAnimals(animalTypes: [AnimalType!]!): FilteredAnimals!
}
enum AnimalType {
MAMMAL
BIRD
FISH
}
type FilteredAnimals {
totalCount: Int!
paginate(pagingOptions: PagingOptions!): [Animal!]!
}
type PagingOptions {
currentPage: Int!
itemsPerPage: Int!
}
type Animal {
name: String!
}
query DisplayAnimal(
$animalTypes: [AnimalType!]!
$pagingOptions: PagingOptions!
) {
mammal: displayAnimals(animalTypes: [MAMMAL]) {
totalCount
}
bird: displayAnimals(animalTypes: [BIRD]) {
totalCount
}
fish: displayAnimals(animalTypes: [FISH]) {
totalCount
}
displayAnimals(animalTypes: $animalTypes) {
animals {
totalCount
paginate(pagingOptions: $pagingOptions) {
name
}
}
}
}
summary
resolver on backend, leading to lesser code.GraphQL Alias is a powerful feature, thus remember to incorporate it when designing the schema.
Actually I wrote this for my workplace team. I decided to post it here because maybe others might find it helpful.
23