February 19, 2021

What is a GraphQL query? GraphQL query examples using Apollo Explorer

Khalil Stemmler

Khalil Stemmler

Queries are the one of the first things we learn about in GraphQL. Combined with great tooling, GraphQL’s declarative approach to asking for the data you want makes the query-writing experience quite enjoyable.

In this post, we’ll cover what GraphQL queries are and how they work. We’ll also learn how to write and execute GraphQL queries using Apollo Explorer: a powerful GraphQL IDE.

Understanding GraphQL queries

What is a GraphQL query?

In GraphQL, there are two primary operations we can perform: queries and mutations.

  • Queries fetch data – like a GET in rest
  • Mutations change data – like a DELETE or a POST in REST

Some people use the word query to refer to both GraphQL queries and mutations, but I prefer to use the word operation instead.

What do GraphQL queries look like?

Here’s an example of a GraphQL query written three different ways.

# GraphQL query with the query and name keywords
query GetPets {
  pets {
    name 
    petType
  }
}

# GraphQL query with just the query keyword
query {
  pets {
    name
    petType
  }
}

# GraphQL query with neither the query or name keyword
{
  pets {
    name 
    petType
  }
}

All three of these queries are functionally equivalent.

In GraphQL, the query and name keywords are optional. However, it’s recommended to use both of them anyway to:

  1. Distinguish the operation type
  2. Make it easier for your teammates to know what your query is for

The other interesting thing to note is that we use nesting to get related data. In the query examples above, we ask for the name and petType fields, which are sub-fields of the pets type.

GraphQL query results

When we ask for data, we get a response back in a similar shape to the query, most commonly in JSON format.

If we executed our GetPets query above, our data would look like the following.

How to execute GraphQL queries

We know what queries look like and we know what to expect in response when we write them. The next question is: how do we execute them?

It’s important to know that since GraphQL queries are just plain strings, we can use a variety of approaches to fetch data. Among the many options, some that come to mind are:

  • curl
  • fetch
  • GraphQL client libraries (like Apollo Client)

And one other option: a GraphQL IDE.

When I’m building out a new GraphQL API, I typically recommend using a free GraphQL IDE like Apollo Explorer. Explorer connects to your GraphQL API running on your local machine and gives you a workspace to run build, run, and save queries.

The less time I spend manually writing queries, the better. For someone just getting started with GraphQL, it’s definitely recommend it for working with a local GraphQL API.

We’ll use Explorer to demonstrate writing and running GraphQL queries.

If you’re curious to learn about the other approaches, read “4 Ways to Call a GraphQL API“.

Setup

We’re going to use a minimal discography GraphQL API example. It lives in the examples folder in the Apollo Server Starter on GitHub.

1. Clone the repo and start the server

Let’s clone the GitHub repo and start up the initial starter server.

git clone https://github.com/apollographql/apollo-server-starter
cd apollo-server-starter
npm run start:dev

If all goes well, you should see a message telling you that your server is ready at http://localhost:4000.

2. Connect to your graph in Apollo Explorer

Next, we want to connect to our local graph from Explorer.

Head over to Apollo Studio. If you don’t already have an account, you can create one using your GitHub account.

When you’re in, you’ll want to click the “New graph” button at the top right.

Next, you’ll be prompted to give your new graph a title and choose a graph type.

  • Title: You can name it whatever you want – I’m going to name mine Discography
  • Graph type: Select Development under graph types. A dev graph lets you connect to a graph running locally on your machine.

Finally, select Create Graph.

You should now be in the Explorer, connected to our local graph running on http://localhost:4000.

3. Test our connection

Let’s test our connection. We’re currently hooked up to the default starter server which has the following server config.

const { ApolloServer, gql } = require("apollo-server");

// Construct a schema, using GraphQL schema language
const typeDefs = gql`
  type Query {
    hello: String
  }
`;

// Provide resolver functions for your schema fields
const resolvers = {
  Query: {
    hello: (root, args, context) => "Hello world!"
  }
};

const server = new ApolloServer({
  typeDefs,
  resolvers
});

server.listen().then(({ url }) => {
  console.log(`🚀 Server ready at ${url}`);
});

Our graph only has one thing to query: a hello field that returns a string. Let’s use that to test out our connection.

Ensure you have the following query in your Operations window.

query ExampleQuery {
  hello
}

And if we run the example by clicking the blue play button, we should get a JSON result back that says “Hello world!”

Boo-yah. There it is. We’re all set up and ready to go!

Let’s try some less trivial examples out.

Examples

Start the discography example graph

Let’s stop the current server that we’re running by inserting a CTRL-Z into our console, then run the following command to start up the discography GraphQL API example included in the starter repo.

npm run start:example discography

Confirm that the server is running by checking the console.

In the Explorer, you should also notice that our ExampleQuery ‘s hello field has a red line through it now. That’s because our graph has changed from the default starter graph in the starter repo to the example discography one.

Let’s clear the existing query from the operation editor. Now we’re ready to rock & roll with some custom queries.

Observe the GraphQL schema

The discography schema in discography/examples/index.js has the following shape.

const typeDefs = gql`

  enum Genre {
    Pop,
    Rock,
    Alternative
    HipHop
  }

  type Track {
    title: String!
    number: Int!
  }

  type Artist {
    name: String!
  }

  type Album {
    title: String!
    artist: Artist!
    tracks: [Track!]!
    genre: Genre!
  }

  type Query {
    albums(genre: Genre): [Album!]!
    album(title: String!): Album
  }
`;

The key things to note about this GraphQL schema are:

  • There are two top-level fields we can query: albums and album
  • The albums field returns a list of albums and has an optional Genre variable.
  • The album field returns either a single album or null. To query this, we need to pass in a value for the title variable.

Example #1: Getting a list of data ━ GetAllAlbums

The first query we want to write is to fetch all albums.

We can compose the query by clicking the fields we want in the Documentation window on the left, starting with the top-level albums field. Then we can selected the nested fields we want beneath it.

Here’s a demonstration.

Pretty snappy, right? Much better than typing all of that out by hand.

If we press the blue Query button, you’ll see that it fires off the query and displays the result in the Response window on the right-hand side.

The composed GraphQL query looks like this:

query Query($albumsGenre: Genre) {
  albums(genre: $albumsGenre) {
    title
    tracks {
      number
      title
    }
    artist {
      name
    }
  }
}

Explorer automatically lines up the possible variables you can use. Since we didn’t use them for this GraphQL query, we could simplify our query by writing it like this:

query Query {
  albums {
    title
    tracks {
      number
      title
    }
    artist {
      name
    }
  }
}

Even better yet, we should give our query a name. As I mentioned before, it’s a good practice to name our queries so that other developers quickly understand what our query does.

query GetAllAlbums {
  albums {
    title
    tracks {
      number
      title
    }
    artist {
      name
    }
  }
}

Perfect.

Example #2: Getting a specific item ━ GetAlbumByTitle

Now we’re going to get a specific album, filtering in on the title field. This means we’re going to be using variables this time.

Let’s clear our operation window and click the back arrow to get ready to write our next query.

To write this query, I’m going to start by selecting the album field and then all the sub-fields I want to display (title, artist, genre, tracklist). After that, I’m going to to search for the album by typing its name in the Variables window towards the bottom-middle part of the screen.

See the demonstration below.

It worked!

Again, I recommend giving your query a good name. Your teammates will thank you. Here’s what the query looks like.

query GetAlbumByTitle($albumTitle: String!) {
  album(title: $albumTitle) {
    title
    artist {
      name
    }
    genre
    tracks {
      title
      number
    }
  }
}

Summary

  • A GraphQL operation can either be a query or a mutation. Queries fetch data and mutations change data (see here for how to use mutations in a GraphQL client library).
  • We learned that we use nesting to ask for related data in a GraphQL query.
  • We learned that the query and name keywords for a GraphQL operation are optional, but it’s recommended to use both to keep your queries readable and understandable.
  • Since GraphQL queries are plain strings, we can use a variety of tools to write them.
  • We learned how to use the Explorer GraphQL IDE to query a local GraphQL API with the dev graphs feature.

Conclusion

Got 30 minutes? Want to take our completely free GraphQL course?

You’ll learn the core components of a full-stack GraphQL app with Apollo through an interactive tutorial.

You can get started here. Enjoy!

Written by

Khalil Stemmler

Khalil Stemmler

Read more by Khalil Stemmler