Sorting and filtering in GraphQL

Jérémie Astori

GraphQL Summit — San Francisco — 30 October 2019

Lee Byron commenting that there is no sorting/filtering support in GraphQL

graphql/graphql-js#640

Jérémie's profile picture
Jérémie Astori

@astorije
[···]

CloudHealth by VMware logo World Wide Web (W3C) logo

What are you looking for?
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
movies with
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
movies with
  • movies with the rock
  • movies with kevin hart
  • movies with will smith
  • movies with the joker
  • movies with adam sandler
  • movies with twins
  • movies with rebel wilson
  • movies with dwayne johnson

Sorting


              {                          
                moviesWithTheRock {
                  title
                }
              }
            

              {
                "moviesWithTheRock": [
                  { "title": "The Mummy Returns" },
                  { "title": "Rampage" },
                  { "title": "Fast Five" },
                  { "title": "Hobbs & Shaw" },
                  { "title": "Jumanji: Welcome to the Jungle" },
                  { "title": "San Andreas" },
                  { "title": "Get Smart" },
                  { "title": "The Other Guys" },
                  […]
                ]
              }
            

              {
                moviesWithTheRock(sort: {
                  field: title,
                  order: DESC  
                }) {
                  title
                }
              }
            

              {                                                 
                "moviesWithTheRock": [
                  { "title": "You Again" },
                  { "title": "Why Did I Get Married Too?" },
                  { "title": "Walking Tall" },
                  { "title": "Tooth Fairy" },
                  { "title": "The Scorpion King" },
                  { "title": "The Rundown" },
                  { "title": "The Other Guys" },
                  { "title": "The Mummy Returns" },
                  […]
                ]
              }
            

              {                          
                moviesWithTheRock(sort: {
                  field: title
                }) {
                  title
                }
              }
            

              {                                                 
                "moviesWithTheRock": [
                  { "title": "Baywatch" },
                  { "title": "Be Cool" },
                  { "title": "Beyond the Mat" },
                  { "title": "Central Intelligence" },
                  { "title": "Doom" },
                  { "title": "Empire State" },
                  { "title": "Fast & Furious 6" },
                  { "title": "Fast Five" },
                  […]
                ]
              }
            
If the value passed as an input to a list type is not a list, then the result of input coercion is a list of size one, where the single item is the provided value.

GraphQL specification

moviesWithTheRock(sort: [Sort!])


              {
                moviesWithTheRock(sort:
                  { field: title }
                ) {
                  title
                }
              }
            


              {
                moviesWithTheRock(sort:
                  [{ field: title }]
                ) {
                  title
                }
              }
            

              {
                moviesWithTheRock(sort: [
                  { field: year, order: DESC },
                  { field: title }             
                ]) {
                  year
                  title
                }
              }
            

              {
                "moviesWithTheRock": [
                  { "year": 2019, "title": "Fighting with My Family" },
                  { "year": 2019, "title": "Hobbs & Shaw" },
                  { "year": 2018, "title": "Rampage" },
                  { "year": 2018, "title": "Skyscraper" },
                  { "year": 2017, "title": "Baywatch" },
                  { "year": 2017, "title": "Jumanji: Welcome to the Jungle" },
                  { "year": 2017, "title": "The Fate of the Furious" },
                  { "year": 2016, "title": "Central Intelligence" },
                  […]
                ]
              }
            

              type MovieWithTheRock {
                year: Int!
                title: String!
              }

              enum SortableField {
                year
                title
              }
            

              enum SortOrder {
                ASC
                DESC
              }

              input Sort {
                field: SortableField
                order: SortOrder = ASC
              }
            

              type Query {
                moviesWithTheRock(sort: [Sort!]): [MovieWithTheRock!]      
              }
            

Filtering


              {                                       
                moviesWithTheRock(filter: {
                  title: { contains: "Fast" }
                }) {
                  title
                }
              }
               
               
               
            

              {                                         
                "moviesWithTheRock": [
                  { "title": "Fast & Furious 6" },
                  { "title": "Fast Five" },
                  { "title": "Faster" }
                ]
              }
               
               
            

              {                                       
                moviesWithTheRock(filter: {
                  title: {
                    contains: ["Fast", "Furious"]
                  }
                }) {
                  title
                }
              }
               
            

              {
                "moviesWithTheRock": [
                  { "title": "Fast & Furious 6" },
                  { "title": "Fast Five" },
                  { "title": "Faster" },
                  { "title": "Furious 7" },             
                  { "title": "The Fate of the Furious" }
                ]
              }
            

              {
                moviesWithTheRock(filter: {
                  or: [                               
                    { title: { contains: "Fast" } },  
                    { title: { contains: "Furious" } }
                  ]                                   
                }) {
                  title
                }
              }
            

              {
                "moviesWithTheRock": [
                  { "title": "Fast & Furious 6" },
                  { "title": "Fast Five" },
                  { "title": "Faster" },
                  { "title": "Furious 7" },
                  { "title": "The Fate of the Furious" }
                ]
              }
            
Faster

looksUpset: true

The Scorpion King

looksUpset: false

The Scorpion King

looksUpset: true

Jumanji: Welcome to the Jungle

looksUpset: false


              {
                moviesWithTheRock(filter: {
                  and: [                   
                    { looksUpset: false }, 
                    { year: { gte: 2018 } }
                  ]                        
                }) {
                  title
                }
              }
            

              {
                "moviesWithTheRock": [
                  { "title": "Hobbs & Shaw" },
                  { "title": "Fighting with My Family" },
                  { "title": "Skyscraper" }
                ]
              }
            

              type MovieWithTheRock {
                looksUpset: Boolean!
                year: Int!
                title: String!
              }

              input Filter {
                looksUpset: Boolean
                year: IntFilter
                title: StringFilter

                and: [Filter!]
                or: [Filter!]
                not: Filter!
              }
            

              input StringFilter {
                equals: String
                contains: String
              }

              input IntFilter {
                equals: Int
                gt: Int
                gte: Int
                lt: Int
                lte: Int
              }
            

              type Query {
                moviesWithTheRock(filter: Filter!): [MovieWithTheRock!]  
              }
            

Conclusion

They all implement a different format.

https://xkcd.com/927/


            {
              moviesWithTheRockConnection(
                first: 10,
                filter: { year: { gte: 2015 } },
                sort: { field: title }          
              ) {
                edges {
                  node {
                    title
                  }
                }
                pageInfo {
                  hasNextPage
                }
              }
            }
          

Thanks!

Slides: https://astori.fr/graphql-summit