GraphQL Overview – Getting Started with GraphQL and Node.js

RisingStack's services:

Sign up to our newsletter!

In this article:

We’ve just released Graffiti: it transforms your existing models into a GraphQL schema. Here is how.

ReactEurope happened last week in the beautiful city of Paris. As it was expected and long-awaited, Facebook released their implementation of the GraphQL draft.

What is GraphQL?

GraphQL is a query language created by Facebook in 2012 which provides a common interface between the client and the server for data fetching and manipulations.

The client asks for various data from the GraphQL server via queries. The response format is described in the query and defined by the client instead of the server: they are called client‐specified queries.
The structure of the data is not hardcoded as in traditional REST APIs – this makes retrieving data from the server more efficient for the client.

For example, the client can ask for linked resources without defining new API endpoints. With the following GraphQL query, we can ask for the user specific fields and the linked friends resource as well.

{
  user(id: 1) {
    name
    age
    friends {
      name
    }
  }
}

In a resource based REST API it would look something like:

GET /users/1 and GET /users/1/friends

or

GET /users/1?include=friends.name

GraphQL overview

It’s important to mention that GraphQL is not language specific, it’s just a specification between the client and the server. Any client should be able to communicate with any server if they speak the common language: GraphQL.

Key concepts of the GraphQL query language are:

  • Hierarchical
  • Product‐centric
  • Strong‐typing
  • Client‐specified queries
  • Introspective

I would like to highlight strong-typing here which means that GraphQL introduces an application level type system. It’s a contract between the client and server which means that your server in the background may use different internal types. The only thing here what matters is that the GraphQL server must be able to receive GraphQL queries, decide if that it is syntactically correct and provide the described data for that.

For more details on the concept of GraphQL check out the GraphQL specification.

Where is it useful?

GraphQL helps where your client needs a flexible response format to avoid extra queries and/or massive data transformation with the overhead of keeping them in sync.

Using a GraphQL server makes it very easy for a client side developer to change the response format without any change on the backend.

With GraphQL, you can describe the required data in a more natural way. It can speed up development, because in application structures like top-down rendering in React, the required data is more similar to your component structure.

Check out our previous query and how similar it is to the following component structure:

<App>
  <User>
    <Friend/>
    <Friend/>
  </User>
</App>

Differences with REST

REST APIs are resource based. Basically what you do is that you address your resources like GET /users/1/friends, which is a unique path for them. It tells you very well that you are looking for the friends of the user with id=1.

The advantages of REST APIs are that they are cacheable, and their behaviour is obvious.

The disadvantage is that it’s hard to specify and implement advanced requests with includes, excludes and especially with linked resources. I think you have already seen requests like:
GET /users/1/friends/1/dogs/1?include=user.name,dog.age

This is exactly the problem what GraphQL wants to solve. If you have types of user and dog and their relations are defined, you can write any kind of query to get your data.

You will have the following queries out of the box:

  • get name of the user with id=1
{
 user(id: 1) {
   name
 }
}
  • get names for friends of the user with id=1
{
 user(id: 1) {
   friends {
     name
   }
 }
}
  • get age and friends of the user with id=1
{
 user(id: 1) {
   age
   friends {
     name
   }
 }
}
  • get names of the dogs of the friends of the user with id=1 🙂
{
 user(id: 1) {
   friends {
     dogs {
       name
     }
   }
 }
}

Simple right? Implement once, re-use it as much as possible.

GraphQL queries

You can do two type of queries with GraphQL:

  • when you fetch (get) data from your server and the
  • when you manipulate (create, update, delete) your data

GraphQL queries are like JSON objects without properties:

// a json object
{
  "user": "name"
}
// a graphql query
{
  user {
    name
  }
}

I already showed some queries for getting data from the GraphQL server, but what else can we do?

We can write named queries:

{
  findUser(id: 1)
}

you can pass parameters to your query:

query findUser($userId: String!) {
  findUser(id: $userId) {
    name
  }
}

With the combination of these building blocks and with the static typing we can write powerful client specified queries. So far so good, but how can we modify our data? Let’s see the next chapter for mutations.

GraphQL mutations

With GraphQL mutation you can manipulate data:

mutation updateUser($userId: String! $name: String!) {
  updateUser(id: $userId name: $name) {
    name
  }
}

With this, you can manipulate your data and retrieve the response in the required format at the same time – pretty powerful, isn’t it?

The recommendation here is to name your mutations meaningful to avoid future inconsistencies. I recommend to use names like: createUserupdateUser or removeUser.

GraphQL through HTTP

You can send GraphQL queries through HTTP:

  • GET for querying
  • POST for mutation

Caching GraphQL requests

Caching can work the same way with GET queries, as you would do it with a classic HTTP API. The only exception is when having a very complex query – in that case you may want to send that as a POST and use caching on a database/intermediary level.

Other Transport layers

HTTP is just one option – GraphQL is transport independent, so you can use it with websockets or even mqtt.

GraphQL example with Node.js server

The Facebook engineering team open-sourced a GraphQL reference implementation in JavaScript. I recommend checking their implementation to have a better picture about the possibilities of GraphQL.

They started with the JavaScript implementation and also published an npm library to make GraphQL generally available. We can start playing with it and build a simple GraphQL Node.js server with MongoDBAre you in? 😉

The GraphQL JS library provides a resolve function for the schemas:

user: {
  type: userType,
  args: {
    id: {
      name: 'id',
      type: new GraphQLNonNull(GraphQLString)
    }
  },
  resolve: (root, {id}) => {
    return User.findById(id);
  }
}

The only thing what we have to do here is to provide the data for the specific resolve functions. These functions are called by GraphQL JS in parallel.

We can generate a projection for our MongoDB query in the following way:

function getProjection (fieldASTs) {
  return fieldASTs.selectionSet.selections.reduce((projections, selection) => {
    projections[selection.name.value] = 1;

    return projections;
  }, {});
}

and use it like:

resolve: (root, {id}, source, fieldASTs) => {
  var projections = getProjection(fieldASTs);
  return User.findById(id, projections);
}

This helps optimising the amount of the fetched data from our database.

Check out the Node.js implementation with MongoDB for more details:
https://github.com/RisingStack/graphql-server

Take a look at Graffiti: it transforms your existing models into a GraphQL schema.

Share this post

Twitter
Facebook
LinkedIn
Reddit