GraphQL 101

Today we will talk about a powerful technology and specification created by Facebook, GraphQL.

 According to GraphQL main site: 

"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. GraphQL isn't tied to any specific database or storage engine and is instead backed by your existing code and data."

So as you can see, GraphQL proposes a change in the way a client asks for data from a server. Instead of needing to know several endpoints, the client now only needs to pass a query asking for the desired data. This is, indeed, very powerful! For example, if a client’s data requirements change, it is no longer necessary to reflect that change in the backend - the client can simply change the query according to its needs. 

Another powerful feature is that you can specify all the data you need and query it in an unique request. With a traditional Rest service, on the other hand, it would be necessary to send more than one request to get the same data.  Eliminating this necessity creates spave for some useful optimizations. For example, a query could be parallelized in the server, dramatically reducing the time spent.

 As a language, GraphQL query is very simple and intuitive to master. A basic example is below:

{
    author {
      name
    }
}

 The response of a GraphQL implementing server is in JSON format and must reflect the format of the query. A response for the query above could be: 

 "data": {
    "author": {
        "name": "Abraao"
    }
}

 As previously mentioned, GraphQL is also a specification and can be implemented in any language and platform. In this article I will present a brief overview of its features. When you're ready to learn more, you can access the specification site: http://facebook.github.io/graphql/.

Querying

So how does querying look? Let's start with some code:

{
    fruit {
        _id
        name
    }
}

 A possible response could be:

"data":{
    "fruit":{
        "_id": "123",
        "name": "Apple"
    }
}

 As you can see, the GraphQL query is basically about defining the fields you want to retrieve. The execution of the query above brings the field fruit of the root of the graph (also called "root query fields").

 Now let's look at a more complex query:

post(_id: "123") {
        description
        author {
            _id
            name
        }
}

 A result could be something like:

"data":{
    "post":{
        "description":"GraphQL 101",
        "author":{
            "_id":0,
            "name":"Abraao"
        }
    }
}

 The query above contains powerful features of GraphQL, such as nested querying (author field) and arguments (the post _id). 

 Nested querying allow us to retrieve both primary fields and their nested fields as needed. In other words, we can go deeper in our graph as required.

 Arguments allow us to filter the results. A query is able to receive multiple arguments, even in the nested fields. In the example above, we were able to filter the post by its id.

Mutations

Up until this point, we've looked at how to query for data from a GraphQL implementing server. In the event that we need to insert or change data, GraphQL provides what it calls "mutations".  According to the GraphQL official site:

 "In REST, any request might end up causing some side-effects on the server, but by convention it's suggested that one doesn't use GET requests to modify data. GraphQL is similar - technically any query could be implemented to cause a data write. However, it's useful to establish a convention that any operations that cause writes should be sent explicitly via a mutation."

 Let's see some examples:

mutation {
    createAuthor(
        _id: "paul",
        name: "Paul Washer",
        twitter: "@paulwasher"
    ) {
        _id
        name
    }
}

The response could be:

"data":{
    "author":{
        "_id":"paul",
        "name":"Paul Washer"
    }
}

 As you can see in the example above, it's not hard understand the mutation. Basically, it creates a new author on the server side and returns the written field with its id and name fields. We can also see that, as opposed to simple querying, the values of the mutated fields are settled in the mutation, and the key word mutation should be present at the root of the query.

 Another exciting feature of GraphQL its ability to accept multiple mutations sent together. For example:

mutation {

    paul: createAuthor(
        _id: "paul",
        name: "Paul Washer",
        twitter: "@paulwasher"
    ) {
        _id
        name
    }

    piper: createAuthor(
        _id: "piper",
        name: "John Piper",
        twitter: "@JohnPiper"
    ) {
        _id
        name
    }
}

 The response would be:

"data":{
    "paul":{
        "_id":"paul",
        "name":"Paul Washer"
    },
    "piper":{
        "_id":"piper",
        "name":"John Piper"
    }        
}

 In the example above, we can see a feature called "result variable". In this case, each result from the mutation is put in a previously specified variable.

Conclusion

The aim of this article was to give a brief description of GraphQL and its features. Hopefully it helps anyone interested in using it! Clearly, the tool has some incredibly useful components, and I believe we'll see its presence in the market increase due to its ability to solve common issues related to RESTful services.

Long term, it doesn't seem that GraphQL aims to replace RESTful services, since they can be used together. But that's a conversation for another day.

An excellent, free online course for those interested in studying GraphQL: https://learngraphql.com

Are you already using GraphQL in your projects? What do you think? Share your experience in the comments!


Author

Abraao Carmo

Java Software Engineer at AvenueCode, with more than 16 years of experience.