Loading...

Over the past decade REST has been the standard for designing APIs. While it offers great features like stateless servers – it has shown it’s age and is too inflexible to keep up with the intense full-steam ahead approach GraphQL with the help of Apollo has taken.

A common use case for using GraphQL is when the client needs the data from multiple sources. With GraphQL you can aggregate the data and let the client consume it from a single point in a standardized way.

Another use case is when there are multiple different clients which are using different data. Most likely, those clients will have to do several requests just to fetch needed data and will be prone to over-fetching and under-fetching. With GraphQL you can let every client choose which data to fetch.

I will go through some of the core concepts of GraphQL / Apollo-Server,

  • Schema and Types
  • Fetching Data(Queries)
  • Writing Data(Mutations)

Type System

GraphQL query language is all about selecting fields in objects. The fields can contain an Array(Of other fields), String, ID, Int, or a Float.  For example:

Schema:


type Band {
  id: ID
  name: String
  topHits: [topHits!]!
  leadSinger: leadSinger
}

type leadSinger {
  id: ID
  name: String!
  band: [Band]
}

type topHits {
  id: ID
  songName: String!
}

type Query {
  artists: [Band]
  leadSingers: [leadSinger]
}

Above we set up the type Band, which has an ID, name, topHits, and leadSinger.

topHits is an array that cannot be null or undefined(Established by the '!' inside and outside the array),

leadSinger is a separate schema type that is used by band, the rational for using another schema type for leadSinger is so the data can be more specific and more available.

With the Apollo Playground GUI enabled we will make the following query:


query {
 Band {
    name
    topHits
 }
 leadsinger {
  name
  band
 }
}

A query is done with the word query first followed by an object that will require the data you want to return, is this example we query Band and we want name and topHits returned, we also query leadSinger and request name and band to be returned.

What’s returned:


{
  "data": {
    "band": {
      "name" : 'Slayer',
      "topHits": [
        "Bloodline",
        "War Ensemble",
        "Repentless"
      ]
    }
    "leadsinger": {
      "name": "Tom Araya",
      "band": "Slayer"
      }
    }
}

All that data with a single endpoint, do you see how powerful(and cheap) this can be?

Query Type:

In the Schema you’ll find a type called Query which in REST would be called a GET request, in this type we listed out exactly what we want to query, in this example it’s Band. It returns what we specified within the Band type:


type Band {
  id: ID
  name: String
  topHits: [topHits!]!
  leadSinger: leadSinger!
}

type Query {
  bands: [Band]
  leadSingers: [leadSinger]
}

A Query is performed exactly like this:


query {
  Band {
    name
    topHits
  }
}
#Returns:
{
  "data": {
    "band": {
      "name" : 'Slayer',
      "topHits": [
        "Bloodline",
        "War Ensemble",
        "Repentless"
      ]
    }
  }
  

Mutation Type:

Okay great, we can read the data… what if we wanted to change it?

Using the same schema:


type Band {
  id: ID
  name: String
  topHits: [topHits!]!
  leadSinger: leadSinger
}

type leadSinger {
  id: ID
  name: String!
  band: [Band]
}

type topHits {
  id: ID
  songName: String!
}

type Query {
  artists: [Band]
  leadSingers: [leadSinger]
}

Let’s define the Mutation Type:


type Mutation {
  addBand(name: String, leadSinger: String, topHits: String ):Band
}

addBand: Names the mutation, inside of the () you target exactly what you want to mutate so here we want to add a band, we need to add the Name which is simply a string, the leadSinger, and the topHits.

When adding something like topHits where there can be multiple just separate the data with a comma.

Band: Returns the type Band after the mutation has run.

Inside of the Apollo GUI:


mutation {
  addBand(name: "Exodus", leadSinger: "Steve Souza", topHits: "Blood in blood out", "Bonded by blood") {
    name
    topHits
    leadSinger {
      name
    }
  }
}

Returns:


{
  "data": {
    "band": {
      "name" : 'Exodus',
      "topHits": [
        "Blood in blood out",
        "Bonded by blood"
      ]
    }
    "leadsinger": {
      "name": "Steve Souza"
    }
  }
  

How great is this? One call gets all the data you would ever want from your API; and that’s just scratching the surface. Apollo enables other great things like Caching, Subscriptions with Web-sockets, Integration Testing, and Custom Scalar types. All out of the box. The real benefit of this, as stated in the beginning, is the reduced over and under fetching. That can result in both insufficient data or too much data, it’s possible you could be over paying for your database service using a REST API that isn’t optimized correctly. GraphQL solves these problems in a cleanly laid out non-complex way.