GraphQL: Queries, Mutuations and Subscriptions

In my first article, I talked about GraphQL types and relationships. This time, I’ll be focusing  on queries, mutations and subscriptions. lI’ll also provide an overview of how variables are used. This is all necessary setup for the final piece in this series, where I’ll show you how to combine all this knowledge together to create a schema for our example application—a document management system.

 

Let’s go!

 

Queries are used by the client to request the data it needs from the server. Unlike REST APIs where there’s a clearly defined structure of information returned from each endpoint, GraphQL always exposes only one endpoint, allowing the client to decide what data it really  needs from a predefined pattern. Here’s an example:

{

 Users {

    name

 }

}

The Users field in our query above is called the root field of the query. Anything that comes after the root field is known as the payload.

 

Since we only added  name in the payload, the query will return a list of all the users in the database like this:

 

{

“Users”: [

  {“name”: “Kingdom”},

  {“name”: “John”},

  {“name”: “Janet”},

  {“name”: “Dan”},

]

}

You’ll notice that the query only returned the names of the users; this is because in the query payload, we specified that we need only the name of each user. This capability is described by GraphQL as ask for what you need and you’ll get exactly that.

Now assuming we need more information about the users, we can decide to add username to the payload

{

Users {

  name

  username

}

}

 

now the server will include the username of each user in its response.

 

{

“Users”: [

  {“name”: “Kingdom”, “username”: ”kingisaac95”},

  {“name”: “John”, “username”: “jony”},

  {“name”: “Janet”, “username”: “jan”},

  {“name”: “Dan”, “username”: “dan_d”},

]

}

 

This way we have more flexibility over the data we receive from the server, which is immensely valuable for many reasons.

For example, assuming we want to request the server to send information of only the last two users who were added, we can use arguments to specify it like this:

 

{

Users(last: 2) {

  name

  username

}

}

 

Note: Zero or more arguments (like last: 2) can be provided for each field in GraphQL. Each argument passed to any field must be defined in the schema.

Thus the server will only return:

 

{

“Users”: [

  {“name”: “Janet”, “username”: “jan”},

  {“name”: “Dan”, “username”: “dan_d”}

]

}

 

Also assuming we have defined an argument in our schema for getting a single document from its title, we can pass in the title as an argument, like this:

 

{

Documents(title: "First post") {

  title

  content

}

}

As expected, this query returns the document whose title matches our argument:

 

{

“Documents”: [

  {“title”: “First post”, “content”: “This is the first post."}

]

}

 

Passing arguments the way we just did is helpful, but in most instances, the arguments needs to be dynamic. GraphQL provides a way for us to pass in dynamic values as arguments— by treating them as variables.

 

Variables are used to factor dynamic values out of the query and pass them as a separate dictionary.

 

For example, if we have a search field where a user types in the title of documents he or she wants to view. To allow that, we’d use variables like this:

 

query Documents($title: String) {

document(title: $title) {

  title

 

  content

}

}

 

($title: String) is the variable definition. title is the variable name and it is prefixed by $, followed by the type in this case String. You can learn more about variables and how they’re used from GraphQL docs.

 

We’ve seen how to retrieve data from the server using queries, but how do we create, update and delete data in GraphQL?

 

Mutations are the key. In GraphQL, mutations are used to CUD:

  • Create new data
  • Update existing data
  • Delete existing data

 

The syntax for mutations look almost the same as queries, but they must start with the mutation keyword. Here’s an example that’ll allow us create a new user:

 

mutation {

createUser(name: “Doe”, username: “jdoe”) {

  name

  username

}

}

 

Notice that the mutation has a root field and payload, just like a query. There are also two arguments passed to the mutation — name and username.

To be able to manage the data of our users effectively, we need to assign a unique identity to each user.

 

GraphQL has a type ID that can be attached to a field. When that is done, the server will automatically generate a unique id for each new object (user).

Recall from the previous article that we created a GraphQL type called User, and now we can update it to include an id field as follows:

 

type User {

id: ID!

name: String!

username: String!

}

 

Now we can update the mutation by passing only the id to the payload. That way the server will return the id of the user we just created.

 

mutation {

createUser(name: “Doe”, username: “jdoe”) {

  id

}

}

 

Subscriptions are a way to create and maintain real time connection to the server. This enables the client to get immediate information about related events.  Basically, a client subscribes to an event in the server, and whenever that event is called, the server will send the corresponding data to the client.

 

Subscriptions are event based. Here’s how they work:

 

Let’s say our document management app allows users to comment on each document and the comments need to be updated in real time. This means:
 

  • For the initial page load, we need to  fetch the previous comments using GraphQL queries.
  • Next, we’ll listen for the new comment and get them through a subscription.
  • We update the UI with a notification that there’s a new comment.

 

We can also create  a subscription that notifies users when a comment is deleted.

In our example, we will want to get updates from the server whenever a new user is created that way we can update the client automatically without having to make a call for it.

 

Here is an example subscription:

 

subscription {

newUser {

  name

  username

}

}

Conclusion

 

In this article we introduced the concepts of queries, mutations and subscriptions. As mentioned in the introduction, we will combine all these concepts  together to create a schema for our example application—a document management system—in the next article.

 

Special thanks to Peggy Rayzis and Eric Baer for reviewing this article.

 



What could you build with Andela Developers?

GET STARTED