How to Write GraphQL Queries
Tags: graphql, api, beginners
Published: 2020-12-03 20:43:52

---
title: How to Write GraphQL Queries
published: true
description: GraphQL queries are what allow GraphQL to be efficient in how it gets data, by allowing you to express only what you need but also exactly everything you need. In this post, we'll see how.
tags: graphql,api,beginners
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/ly4jp5mzrkgolne3k39x.png
canonical_url: https://stepzen.com/blog/how-to-write-graphql-queries
---

GraphQL is often touted for its efficiency when consuming data from APIs. There are two key aspects to its efficiency:

1. **You get only the data you need**. GraphQL will only respond with the fields you specify, meaning it does not need to send unnecessary data across the wire, potentially saving your application - and your users - significant amounts of data over the course of numerous transactions.
2. **You get all the data you need in a single request.** Rather than spread different parts of the data across multiple endpoints, GraphQL lets you get all the data you require from a single request. For example, I can get user information and their order information in a single query rather than hitting two separate endpoints.

Both of these benefits are made possible by the way GraphQL lets you constuct a query, but learning how to write a GraphQL query can take some practice. In this article, we'll look at some of the basics of constucting a query in GraphQL to help you get started. In this post, we'll focus on retreiving data from a GraphQL API (as opposed to modifying, or mutating, the data).

## Getting Set Up

More and more companies are adopting GraphQL for their APIs. GitHub was a early adopter of the technology. The GraphQL spec was open sourced in 2015 and the [GitHub GraphQL API](https://docs.github.com/en/free-pro-team@latest/graphql) was announced [back in 2016](https://github.blog/2016-09-14-the-github-graphql-api/). Pretty much anything you can do in GitHub, you can do via their GraphQL API. Today we are going to use it to retreive user and repository information in order to explore how you write GraphQL queries.

There are two ways to explore the API:

* Use their [API Explorer](https://developer.github.com/v4/explorer). If you log in to your GitHub account, it will allow you to explore the API schema and construct and run queries via a [GraphiQL](https://github.com/graphql/graphiql) interface.
* The alternative is to use a desktop API explorer. If you're a REST API consumer, you may be comfortable using something like [Postman](https://www.postman.com/), which, you'll be pleased to know, [does support GraphQL](https://learning.postman.com/docs/sending-requests/supported-api-frameworks/graphql/). In this post, I'll be using the free, [GraphQL Playground](https://github.com/graphql/graphql-playground), which is an Electron desktop app that can be installed via Homebrew or by [downloading the latest release](https://github.com/graphql/graphql-playground/releases/tag/v1.8.10).

In order to use the API outside the API Explorer, you'll need to [generate a Personal Access Token](https://github.com/settings/tokens). If you choose to use GraphQL Playground, you'll first need to add the API endpoint of `https://api.github.com/graphql`. If you try to run anything, you'll get a 401 error though. To fix this, add an authorization header in the HTTP headers (located on the bottom left side of the application window):

```json
{
  "Authorization":"Bearer MY_TOKEN"
}
```

![HTTP Headers in Playground](https://dev-to-uploads.s3.amazonaws.com/i/1sajcf47as4ifzwj3bcm.png)

Once the HTTP headers are set up, you should be able to click on the Docs tab on the far right to explore the types and queries available within the GitHub API.

![Playground Schema docs](https://dev-to-uploads.s3.amazonaws.com/i/8733y90glrsxh1epiyke.png)

Ok. We're finally ready to start building a query.

## Creating Your First Query

Let's start with a relatively simple query to find out how many people are following the topic of GraphQL on GitHub using the `topic` query. In a RESTful API situation, this might involve calling an endpoint such as `/v3/search/topics` which would return all the details we need. However, every GraphQL query calls the same endpoint, so you must define what you are querying in the request. Luckily, GraphQL IDEs like GraphiQL or the GraphQL Playground will offer code hinting.

Let's start by calling the `topic` query:

```graphql
{
  topic
}
```

You may notice that your GraphQL IDE indicates that there is an error in your request.

![GraphQL query error](https://dev-to-uploads.s3.amazonaws.com/i/si18tptfzi2ptimydt2g.png)

As the error indicates, the `topic` query expects a `name` argument of type string. So let's add our first argument, which is placed in parentheses after the query:

```graphql
{
  topic(name: "graphql")
}
```

You'll note that we're still seeing an error. Why? Well, the way that GraphQL is able to supply you _only the data you need_ is by requiring that you specify the fields you require within your query. There is no equivalent of `select *` in GraphQL, and this is [for a number of good reasons](https://productionreadygraphql.com/blog/2019-10-24-why-you-cant-select-all-fields-on-a-type-in-graphql). So, lets specify some fields within our query.

The `topic` query has 6 fields available, but really we're only interested in the number of people following it, or the `stargazersCount` field:

```graphql
{
  topic(name: "graphql") {
    stargazerCount
  }
}
```

Finally, no errors. Let's run our query. Here's the response:

```json
{
  "data": {
    "topic": {
      "stargazerCount": 12201
    }
  }
}
```

You'll notice that the response matches the query, meaning we don't need to waste time figuring out the structure of the response (something I have spent inordinate amounts of time doing in the past).

### Arguments

In the above example, we had a single argument that was a string. Arguments can be any of the [GraphQL basic types](https://graphql.org/graphql-js/basic-types/) but they can also be an enum or even a custom object type. For example, GitHub's `search` query takes a `searchType` argument that is an enum with the possible values of `ISSUE`,`REPOSITORY` or `USER`.

```graphql
{
  search(query: "GraphQL", type: REPOSITORY) {
    repositoryCount
  }
}
```

Meanwhile, for example, the `repositories` object within a `user` query takes a custom object argument of type `RespositoryOrder` that specifies both the field to order by and the direction in which to order. Here's a snippet from the larger query we'll look at later in this article:

```graphql
...
repositories(orderBy: {field:UPDATED_AT, direction: DESC}) {
...
```

The point here is that GraphQL allows APIs to support very complex querying capabilities in arguments.

## Nested Objects

So far, we have a very simple query that gets only a single field. Let's make this a little bit more complex by adding a nested object to get multiple sets of data in a single query. In this case, let's get a list of related topics to GraphQL within GitHub using the related topics object.

```graphql
{
  topic(name:"graphql") {
    stargazerCount
    relatedTopics {
      name
      stargazerCount
    }
  }
}
```

You'll see that we need to specify the object and then again the fields within that object that we want to retrieve. In this case, `relatedTopics` did not require an arguement. However, if you look at the docs, you'll see that it does have an optional argument of `first` that defaults to 3, meaning it will only send the first 3 results. Let's define that to give us 10 (the maximum the API allows):

```graphql
{
  topic(name:"graphql") {
    stargazerCount
    relatedTopics(first: 10) {
      name
      stargazerCount
    }
  }
}
```

As you can see, you can specify arguments not just on the primary query but on nested object queries as defined by the schema.

## Aliases

Now let's imagine that we want to get the stargazer count for both GraphQL and JavaScript in a single request. You might try something like this:

```graphql
{
  topic(name: "graphql") {
    stargazerCount
  }
  topic(name: "javascript") {
    stargazerCount
  }
}
```

That would give you an error however because we have defined conflicting queries in a single request. To solve this, we need to use an alias on each of the queries:

```graphql
{
  graphql:topic(name: "graphql") {
    stargazerCount
  }
  javascript:topic(name: "javascript") {
    stargazerCount
  }
}
```

This will return a response containing the aliases you specified.

```json
{
  "data": {
    "graphql": {
      "stargazerCount": 12203
    },
    "javascript": {
      "stargazerCount": 73700
    }
  }
}
```

It's worth noting that the alias can be any string you want, though it cannot start with a number or contain any special characters other than an underscore (though it can start with an underscore).

## Fragments

Let's imagine that we wanted to make this query get more than just the `stargazerCount`. We wouldn't want to have to repeat this code for each aliased query. This is where fragments come in. They can represent reusable pieces of query code. For example, instead of writing this:

```graphql
{
  graphql:topic(name:"graphql") {
    stargazerCount
    relatedTopics(first: 10) {
      name
      stargazerCount
    }
  }
  javascript:topic(name:"javascript") {
    stargazerCount
    relatedTopics(first: 10) {
      name
      stargazerCount
    }
  }
}
```
...we can write this:

```graphql
{
  graphql:topic(name:"graphql") {
    ...topicDetails
  }
  javascript:topic(name:"javascript") {
    ...topicDetails
  }
}

fragment topicDetails on Topic {
	stargazerCount
    relatedTopics(first: 10) {
      name
      stargazerCount
    }
}
```

We define the fragment and give it a name (`topicDetails` in this case). You must define the type it is a fragment on (`Topic` in this case) for validation purposes. Then we can reuse the fragment by referencing it's name prefixed by three dots (i.e. `...topicDetails` in this case) wherever we need to reuse it. While we didn't save a ton of code in this example, this can be particularly useful when you find yourself repeating large chunks of code in a complex query.

## Variables

The last topic I want to discuss here is variables. Let's imagine I wanted to create a query that gets the user profile information and recent repositories for a user. This wouldn't work if I had to pass a hardcoded user string. Instead, GraphQL allows me to define a variable and then pass in a variables object to the query to populate the variables.

First, let's look at our query. This query basically gives us everything we might want to know to construct a profile page for a GitHub user (perhaps for a developer portfolio home page or something):

```graphql
query GitHubUserProfile($username: String!)  {
  user(login:$username) {
    name
    company
    bio
    twitterUsername
    websiteUrl
    url
    repositories(first: 10, privacy: PUBLIC, orderBy: {field:UPDATED_AT, direction: DESC}) {
      totalCount
      edges {
        node {
          name
          description
          url
        }
      }
    }
  }
}
```

Not related to variables, but up until now we have been using an anonymous operation (i.e. wrapping the query in curly braces), but best practice says we should define the operation type and name. In this case, our operation type is a `query` and the name is `GitHubUserProfile`. There are other operation types such as a mutation, which modifies data on the server, and a subscription, which subscribes to updates to changes from the server.

You'll notice I have defined a variable `$username` (all variables must be prefixed by a `$`) of type string. The exclamation point (`!`) indicates that this variable is a required argument. Within the `user` query we now reference the `$username` variable as the value for the `login` argument.

To specify that argument, we need to pass in a JSON object containing a value for `username`. We can do that in GraphQL Playground via the variables tab in the bottom left of the application.

![GraphQL variables](https://dev-to-uploads.s3.amazonaws.com/i/6czzei4ahgeyw7u01ckg.png)

In this case, I've supplied my own GitHub username:

```json
{
  "username": "remotesynth"
}
```

...and you can see the result of running the query on the right (I won't duplicate the result here as it is rather long).

## Where To Go Next

This isn't a complete guide to queries. There are things like directives, for instance, that I have not touched on here. If you are looking for more details, I recommend the following resources:

* [Queries and Mutations](https://graphql.org/learn/queries/) on [graphql.org](https://graphql.org/)
* [Understanding Queries in GraphQL ](https://www.digitalocean.com/community/tutorials/understanding-queries-in-graphql) by Peter Ekene
* [GraphQL Core Concepts](https://www.howtographql.com/basics/2-core-concepts/) on [howtographql.com/](https://www.howtographql.com/)

Want to know why StepZen chose to use GraphQL? Check out [Why GraphQL?](https://stepzen.com/blog/why-graphql) by StepZen's CEO, Anant Jhingran.

## This Is Awesome, But My Backend Doesn't Support GraphQL

I think GraphQL offers a ton of power for queries, but you may be connecting to first-or-third-party RESTful APIs that haven't yet made the move or to a database backend that doesn't even have an API yet. If so, [StepZen](https://stepzen.com/) can help. We're building a way for you to enable all the backends you connect to to be accessible via a unified GraphQL API. You can learn more and sign up to get access to our private beta at [stepzen.com](https://stepzen.com/).