Getting started with GraphQL and node.js

Muthukumaraswamy
6 min readFeb 24, 2020

--

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.

GraphQL is usually described as a frontend-directed API technology as it allows front-end developers to request data in a much simpler way than ever before. Introduced by Facebook, the objective of this query language is to formulate client applications formed on the instinctive and adjustable format, for portraying their data prerequisites as well as interactions. The best part is the language isn’t dependent on any specific database management system and is actually supported by your current data and coding.

One of the basic problems with conventional REST is the failure of the client to demand a personalized data set. In addition to that, running and controlling multiple endpoints is another difficulty as clients are mostly needed to request data from diversified endpoints.

While establishing a GraphQL server, it’s only important to have single URL for complete data procurement and alteration. Therefore, a user can request a dataset from a server by transferring a query string, mentioning what they need.

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!) {
User(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: createUser, updateUser 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 .

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 of 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 MongoDB.

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 to optimize the amount of the fetched data from our database.

Article originally written in Linked in

--

--

No responses yet