GraphQL

The Intro

  • What is GraphQL ?
  • What does it solve ?
  • How does it work ?
  • Why do we need it ?

What is GraphQL ?

GraphQL is a new API standard that provides an efficient , flexible, powerful alternative for REST

GraphQL isn't tied to any specific database or storage engine and is instead backed by your existing code and data.

GraphQL is an open-source data query and manipulation language for APIs, and a runtime for fulfilling queries with existing data.

GraphQL was developed internally by Facebook in 2012 before being publicly released in 2015.

Since 2012, GraphQL's rise has followed the adoption timeline as set out by Lee Byron, GraphQL's creator, with accuracy.

On 7 November 2018, the GraphQL project was moved from Facebook to the newly-established GraphQL Foundation, hosted by the non-profit Linux Foundation.

GraphQL Web Site

Since reveal.js runs on the web, you can easily embed other web content. Try interacting with the page in the background.

What does it solve ?

GraphQL is a query language for your API, and a server-side runtime for executing queries by using a type system you define for your data.

At its core, GraphQL enables declarative data fetching where a client can specify exactly what data it needs from an API.

Instead of multiple endpoints that return fixed data structures, a GraphQL server only exposes a single endpoint and responds with precisely the data a client asked for.

A GraphQL service is created by defining types and fields on those types, then providing functions for each field on each type.

GraphQL - A Query Language for APIs

Not Databases

Example

Let's define simple, related data structure

(NF3)

📘 Books

id name authorId movieId
1 Book 1 11 111
2 Book 2 22 222
3 Book 3 33 333

👨🏻‍💻 Authors

id name age
11 Alex 33
22 David 44
33 Mike 55

⭐️ Stars

id bookId stars
1 2 4
2 1 5
3 2 7

🎥 Movies

id title year
111 Episode I 1999
222 Episode II 2002
333 Episode III 2005

Episode I

📘

⭐️⭐️⭐️⭐️⭐️

👨🏻‍💻 TERRY BROOKS American writer Terence Dean Brooks is an American writer of fantasy fiction. He writes mainly epic fantasy, and has also written two film novelizations. He has written 23 New York Times bestsellers during his writing career, and has sold over 21 million copies of his books in print. Wikipedia Born: January 8, 1944 (age 76 years), Sterling, Illinois, United States Spouse: Judine Brooks Education: Washington and Lee University School of Law ... Nominations: Locus Award for Best Fantasy Novel...

🎬 Episode I

REST

server

HTTP GET /books/2


output:
  {
    "data": {
      "book": {
        "name": "Book2",
        "genre": "Sci-Fi",
        "authorId": "2",
        "movieId": "33"
        "id" :2,
        "meta": "43434r",
        "type": "fdfe"
      }
    }
  }

REST API

🧐


HTTP GET /books/2


output:
  {
    "data": {
      "book": {
        "name": "Book2",
        "genre": "Sci-Fi",
        "authorId: "2",
        "movieId": "33"
      }
    }
  }

REST API

🤔


HTTP GET /books/:id/authors/


output:
{
  "author": {
    "age": 44,
    "name": "Mike",
    "id": "5e5629fc4"
  }
}

REST API

🤨


HTTP GET /books/:id/movies/


output:
"movie": {
  "title": "Episode I",
  "year": "2008",
  "id": "58559"
}


REST API

🤨


HTTP GET /books/:id/stars/


output:
"stars": {
  "stars": 5,
  "id": "3",
  "bookId": "5e562a384e98"
},


REST API

🤨

Rest API


HTTP GET /books/:id

HTTP GET /books/:id/authors/

HTTP GET /books/:id/movies/

HTTP GET /books/:id/stars/

    

{
  "data": {
    "book": {
      "name": "Book2",
      "genre": "222",
      "more": "not relevant fields",
      "author": {
        "age": 44,
        "name": "Mike",
        "id": "5e5629fc4e98b96691966c76",
        "more": "not relevant fields"
      },
      "stars": {
        "stars": 5,
        "id": "3",
        "bookId": "5e562a384e98b96691966c77",
        "more": "not relevant fields"
      },
      "movie": {
        "title": "Episode I",
        "year": 2008,
        "id": "58559",
        "more": "not relevant fields"
      }
    }
  }
}

The problem

  • Overfetching - Download unnecessary data
  •  
  • Underfetching - An endpoint doesn't return enough of the right information, needs to send multiple requests (n+1)

GraphQL

With GraphQL we can retrieve all related data with one single query using only one exposed api

GraphQL


  {
    book(id: "2"){
      name
      genre
      author{
        age,
        name
        id
      }
      stars{
        stars
        id
        bookId
      }
      movie{
        title
        year
        id
      }
    }
  }


{
  "data": {
    "book": {
      "name": "Book2",
      "genre": "222",
      "author": {
        "age": 44,
        "name": "Mike",
        "id": "5e5629fc4e98b96691966c76"
      },
      "stars": {
        "stars": 5,
        "id": "3",
        "bookId": "5e562a384e98b96691966c77"
      },
      "movie": {
        "title": "Episode I",
        "year": 2008,
        "id": "58559"
      }
    }
  }
}

With dynamic fields selection, we just can solve the problem of over and under fetching

GraphQL - Accessing the fields

  {
    book(id: "2"){
      name
      author{
      age 
      }
      stars{
        stars
      }
      movie{
        title
      }
    }
  }


  {
    "data": {
      "book": {
        "name": "Book2",
        "author": {
          "age": 44
        },
        "stars": {
          "stars": 5
        },
        "movie": {
          "title": "Episode I"
        }
      }
    }
  }
GraphQL - Accessing the fields

  {
    book(id: "2"){
      name
      genre
      author{
      age 
      name
      }
      stars{
        stars
      }
      movie{
        title
      }
    }
  }


{
"data": {
  "book": {
    "name": "Book2",
    "genre": "222",
    "author": {
      "name": "Mike",
      "age": 44,
    },
    "stars": {
      "stars": 5,
    },
    "movie": {
      "title": "Episode I",
    }
  }
}
}
GraphQL vs REST

Rapidly changing requirements on a client side don't go well with the static REST

GraphQL was developed to cope with the needs for more flexibility and efficiency in client-server communication

With REST API we are dependent on UI and the Server structure.

Endpoints structured according to the client needs. So every change has a huge influence on a core server, product and UI

With GraphQL this problem just doesn't exist anymore.

With GraphQL we can use low level performance tuning and fields review regardless to the server

With GraphQL frontend and backend completely independent from each other

What if ?

📘 Books

👨🏻‍💻 Authors

🎥 Movies

⭐️ Stars  

Can we still have

the relations ?

Can we still retrieve the data with one single

query ?

Yes, we can !

Yes, we can !

GraphQL - A Query Language for APIs

Not Databases

With One single query you can

Retrieve

Delete

Update

Insert

any data in any Database


{
  "data": {
    "book": {
      "name": "Book2",
      "genre": "222",
      "author": {
        "age": 44,
        "name": "Mike",
        "id": "5e5629fc4e98b96691966c76"
      },
      "stars": {
        "stars": 5,
        "id": "3",
        "bookId": "5e562a384e98b96691966c77"
      },
      "movie": {
        "title": "Episode I",
        "year": 2008,
        "id": "58559"
      }
    }
  }
}

C
R
U
D

mutation {
  addStar(bookId:"5e562a774e98b96691966c78", stars:3) {
  id
}}

mutation {
  addBook(name: 'Episode II') {
    id
}}

mutation {
  deleteMovie(name: 'Episode II') {
    id
}}

mutation {
  updateAuthor(name: 'Mike') {
    id
}}

C
R
U
D

GraphQL

gives you

the

F R E E D O M

of choice

  • How to structure the Data
  • Where to store the Data
  • Combine different technologies by your needs
  • Expose one or multiple endpoint
  • Control who and how will access the data
  • Be ready for rapid grow and changes

How does this magic work ?

server
server
server

type Author {
  name: String!
  age: Int!
}
                            
                            

GraphQL has its own type system that’s used to define the schema of an API. The syntax for writing schemas is called Schema Definition Language (SDL).



  type Author {
    name: String!     
    age: Int!
  }

This type has two fields, they’re called `name` and `age` and are respectively of type String and Int.

The ! following the type means that this field is required.



  type Book {
    name: String!     
    authorId: Author!     
  }

It’s also possible to express relationships between types. In the example of a books application, a Book could be associated with the Author

GraphQL has a clear separation of structure and behavior. The structure of a GraphQL server is — as we just discussed — its schema, an abstract description of the server’s capabilities.

This structure comes to life with a concrete implementation that determines the server’s behavior. Key components for the implementation are so-called resolver functions.

Each field in a GraphQL schema is backed by a resolver.

Definding the type with


    const graphql = require('graphql')
    const { GraphQLObjectType, GraphQLID, 
            GraphQLList,GraphQLString,GraphQLInt } = graphql

    const AuthorType = new GraphQLObjectType({
      name: "Author",
      fields: () => ({
        id: { type: GraphQLID },
        name: { type: GraphQLString },
        age: { type: GraphQLInt },
        books: {
          type: new GraphQLList(BookType),
          resolve: (parent, args) => {
            return Book.find({ authorId: parent.id }) // mongo db
          }
        }
      })
    })

Fetching Data with Queries


  {
    books {
      name
      genre
      id
      author{     
        name
        age
        id
      }
    }
  }
  
  

    {
      "data": {
        "books": [

          {
            "name": "Book1",
            "genre": "1111",
            "id": "5e56294a4e98b96691966c74",    
            "author": {
              "name": "Alex",
              "age": 39,
              "id": "5e56255c62c9836008df46d7"      
            }
          },
          
          ....
        ]
      }
    }
              

Queries with Arguments


  {
    book(id: "5e562...") {   
      name
      genre
      id
      author{     
        name
        age
        id
      }
    }
  }
  
  

    {
      "data": {
            "name": "Book1",
            "genre": "1111",
            "id": "5e56294a4e98b96691966c74",    
            "author": {
              "name": "Alex",
              "age": 39,
              "id": "5e56255c62c9836008df46d7"      
      }
    }
              

So we need some way of making changes to the data that’s currently stored in the backend.

With GraphQL, these changes are made using mutations.

There generally are three kinds of mutations

  • creating new data
  • updating existing data
  • deleting existing data

Writing Data with Mutations


  mutation {

  createBook(name: "Book 10", genre: "Sci-Fi") {    
    name
    id
  }

  updateBook(name: "Book 10", genre: "Sci-Fi") {    
    name
    id
  }

  deleteBook(id: ...) {    
    name
    id
  }
}
  
  

    {
      "data": {
        "name": "Book 10",
        "id": "5e56294a4e98b96691966c74"    
    }
              

Realtime Updates with Subscriptions

Another important requirement for many applications today is to have a realtime connection to the server in order to get immediately informed about important events. For this use case, GraphQL offers the concept of subscriptions.

When a client subscribes to an event, it will initiate and hold a steady connection to the server. Whenever that particular event then actually happens, the server pushes 🤓 the corresponding data to the client.

Unlike queries and mutations that follow a typical “request-response-cycle”, subscriptions represent a stream of data sent over to the client.

😎


              subscription {
                newBook {
                  name
                  genre
                }
              }
            

After a client sent this subscription to a server, a connection is opened between them. Then, whenever a new mutation is performed that creates a new Book, the server sends the information about this book over to the client


              {
                "newBook": {
                  "name": "Book 22",
                  "genre": "Sci-Fi"
                }
              }
            

The Architecture

server
server
DB interface
Multiple DBs/Types

Hybrid

DB and Legacy API or Server

Use Cases

GraphQL server with a connected database
GraphQL server that is a thin layer in front of a number of third party or legacy systems and integrates them through a single GraphQL API
A hybrid approach of a connected database and third party or legacy systems that can all be accessed through the same GraphQL API

Any Type of Technology

Any Type of DB

Any Structure

Any Location

The payload of a GraphQL query (or mutation) consists of a set of fields. In the GraphQL server implementation, each of these fields actually corresponds to exactly one function that’s called a resolver.
The sole purpose of a resolver function is to fetch the data for its field.
When the server receives a query, it will call all the functions for the fields that are specified in the query’s payload.
It thus resolves the query and is able to retrieve the correct data for each field.
Once all resolvers returned, the server will package data up in the format that was described by the query and send it back to the client.

How about the client side ?

Construct and send HTTP request (e.g. with fetch in Javascript)

Receive and parse server response store data locally (either simply in memory or persistent)

Display data in the UI

🤷🏻‍♂️

DEMO & QA