Getting Started with GraphQL

Deepak Kapoor
6 min readAug 4, 2017

--

It was a rainy Friday afternoon in year 2007, I was in the office not in the mood to start something new. Rather than starting a new task I decided to browse the InterWebs. I came across an article about RESTFul APIs. Since then have I rested or what? Okay, I made up most of the stuff about rain, Friday and afternoon. But I am sure about 2007.

Since then all the software I have written has involved some form of interaction with some form of RESTFul service. It has been a good normal relationship. The one in which you have fun when the APIs are well structured. You know that if the end-point has “customer” in it then it has to do something with “customer”. There have been times when I thought SOAP was so much better. Yes, I did have those thoughts. Overall with all it’s ups and down, it has been a good run.

The time has come to stop resting and move on.

Hello GraphQL.

What is GraphQL and Where did it come from?

GraphQL came out of Facebook as did my favourite front-end framework React.

GraphQL according to the spec is a query language for describing the capabilities and requirements of data-models for client-server applications. Some other query languages I have encountered in the wild are SQL, MDX, XQuery, XPath and the list goes on.

The basic idea of a query language is that you describe what you want. Some software understands this language and gives you the data you are after. GraphQL is no different.

So what does a GraphQL query look like? Here is an example

{
author(id: 1) {
name
}
}

The query above will produce data which will look like this

{ "author": { "name": "J K Rowling" } }

As I said earlier that a query has to be understood by some software. This software is implemented as a server with which a client can interact. There are many server implementations available in different languages Java, C#, Python etc.

I wanted to play with GraphQL without setting up a server or a client. While searching for an existing GraphQL API, I came across GitHub’s API v4 which is written in GrahpQL. They also provide a nice little tool online which can be used to run queries against GitHub’s API.

You should check it out at https://developer.github.com/v4/explorer/

When I meet an API for the first time, I like to know what it can do for me. What data can it give me? The way to find this information is by reading API’s documentation. I’d argue that the documentation is the key to API’s popularity.

With GraphQL, the API can describes itself. We can ask the API to tell us what it returns.

I ran a simple query against Github API to tell me what data I can expect from it.

query {
__schema {
types {
name
kind
description
fields {
name
}
}
}
}

In the query above I am asking for all types, their name, kind, a description and the fields supported. The result of the query tells me that there are 335 types available which I can query.

Let us pick one of the types randomly and look at the information it gives us.

Here we can see that type with name “Repository” is an Object and some of the fields it returns are codeOfConduct, commitComment and createdAt.

BTW: That wasn’t random at all. I intentionally picked Repository.

So what is this figuring out thing called. The word is Introspection.

Let’s write another introspection query in which we will ask for all the fields for “Repository” type. We’d like to know the name of the field, it’s description, is it deprecated and the reason for deprecation.

query {
__type(name: "Repository") {
name
fields {
name
description
isDeprecated
deprecationReason
}
}
}

From the result we can see that there are 57 fields available for Repository. The result also included the data we asked for.

You may have noticed that I only asked for the fields of type Repository. The way I did this was by passing in the name parameter with it’s value set to “Repository”

Let’s get some information on a github user. No harm in a little spying 🙂

query {
user(login: "deepak-kapoor") {
name
isHireable
location
repositories(first: 5) {
edges {
node {
id
}
}
}
}
}

In the query above we are asking for some information on user deepak-kapoor. His name, is he hireable (Wink! Wink!), his location and first 5 repositories created by Deepak. Some fields such as repositories on type user require either first or last argument to be passed in as per GitHub’s requirement.

Let’s write a query which retrieves commit comments for a repository along with the login of author who made those comments and url to his/her github profile.

query {
repository(owner: "facebook", name: "react") {
name
commitComments(first: 10) {
edges {
node {
body
author {
login
url
}
}
}
}
}
}

We can retrieve more than one repository in one query. Consider the following query where we are retrieving data for the awesome React repository and the other popular one called Angular.

query {
repository(owner: "facebook", name: "react") {
repositoryName: name
commitComments(first: 10) {
edges {
node {
body
author {
login
url
}
}
}
}
}
repository(owner: "angular", name: "angular") {
repositoryName: name
commitComments(first: 10) {
edges {
node {
body
author {
login
url
}
}
}
}
}
}

What should we get? Data for both React and Angular repository? Not quite. You see this query has an issue.

We have a conflict.

We can get around this situation by using aliases.

query {
reactRepository: repository(owner: "facebook", name: "react") {
repositoryName: name
commitComments(first: 10) {
edges {
node {
body
author {
login
url
}
}
}
}
}
angularRepository: repository(owner: "angular", name: "angular") {
repositoryName: name
commitComments(first: 10) {
edges {
node {
body
author {
login
url
}
}
}
}
}
}

No problems now. We will get back two data objects. One for React and the other for Angular. You will note that we have also aliased the name field to repositoryName.

There is still something bothersome about the query. We are repeating ourselves here by asking for the same commitComments object for both reactRepository and angularRepository. GraphQL has a neat little feature called fragments which can address this situation.

query {
reactRepository: repository(owner: "facebook", name: "react") {
...repositoryFields
}
angularRepository: repository(owner: "angular", name: "angular") {
...repositoryFields
}
}

fragment repositoryFields on Repository {
repositoryName: name
commitComments(first: 10) {
edges {
node {
body
author {
login
url
}
}
}
}
}

By using fragments we got rid of the repetition we had earlier.

I’m starting to like this GraphQL thing now. But (there is always a but) in our query we have hardcoded repository’s owner and name. I’m sure we can do better than this.

GraphQL has a concept of variables which are meant just for this purpose. Let’s see how can they be used.

query ($name: String!, $owner: String!) {
repository(name: $name, owner: $owner) {
name
}
}

In the query above we are saying that this query accepts two variables $name and $owner of type String! The exclamation at the end of String indicates that the value is required.

We are expecting that values for both variables will be passed in. The values will be passed in as a JSON object.

{
"name": "react",
"owner": "Facebook"
}

This query can now be used with any values as you would expect.

GraphQL is not just for reading data. We can also write data. In GraphQL terminology we call it mutation. That will be the topic of another article.

Hope you enjoyed reading.

--

--