GraphQL queries
Using GraphQL queries, you can get all the data you need, and only the data you need, in a single request.
GraphQL is often touted for its efficiency when consuming data from APIs. There are two key aspects to its efficiency:
- You get only the data you need:
GraphQL will only respond with the fields you specify. This means it doesn't 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.
- 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 via a single request. For example, you can get user information and their order information in a single query, rather than sending requests to two separate endpoints.
Both of these benefits are made possible by the way GraphQL lets you construct a query. In the following sections, look at some of the basics of constructing a query in GraphQL to retrieve data.
Get set up to create queries
The GitHub GraphQL API is a large and complex GraphQL API that offers a way to explore many of the GraphQL query features.
There are two ways to explore the API:
- API Explorer:
Use the GitHub API Explorer. When you log in to your GitHub account, the API Explorer enables you to explore the API schema and construct and run queries in a GraphiQL interface.
To use the API outside of the API Explorer, you must generate a Personal Access Token.
- External desktop apps:
Use a desktop app such as:
- Postman: A collaboration platform for API development that supports GraphQL.
- GraphQL Playground: An Electron desktop app that can be installed using Homebrew or by downloading the latest release.
This tutorial uses GraphQL Playground.
Complete the following steps to set up and use the API:
- Add the API endpoint:
https://api.github.com/graphql
for GraphQL Playground. At this point you'll get a 401 error if you try to run anything. You'll fix that in the next step. - Add an
Authorization
header to the HTTP headers (located at the bottom left of the application window):{ "Authorization":"Bearer MY_TOKEN" }
-
Click the Docs tab on the far right to explore the types and queries available within the GitHub API.
Now you're ready to start building a query.
Create your first query
Start with a relatively simple topic
query, to find out how many people are
following a "GraphQL" topic on GitHub.
With a RESTful API, this might involve calling an endpoint such as
/v3/search/topics
that returns all of the necessary details. 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 offer code hinting.
Start by calling the topic
query:
{
topic
}
You might notice that your GraphQL IDE indicates that there is an error in your request.

The error indicates the topic
query expects a name
argument of
type string. So, add your first argument in parentheses after the query:
{
topic(name: "graphql")
}
Even with this change, an error still occurs. Why? GraphQL requires you to specify the fields
required within your query, in order to supply you with only the data you need. There is no
equivalent of select *
in GraphQL, and this is for a number of good reasons. So, let's specify some fields
within the query.
The topic
query has six fields available, but you're only interested in the
number of people following it, or the stargazersCount
field, so modify the query to
look as follows:
{
topic(name: "graphql") {
stargazerCount
}
}
Finally, no errors. Run our query. The response should look similar to the following:
{
"data": {
"topic": {
"stargazerCount": 12201
}
}
}
Notice that the response matches the query, meaning you don't need to waste time figuring out the structure of the response.
Arguments
The example uses a single string argument. In addition to any of the GraphQL basic
types, an argument can also be an enum or even a custom object type. For example, the GitHub
search
query takes a searchType
enum argument that can be set to
ISSUE
,REPOSITORY
or USER
:
{
search(query: "GraphQL", type: REPOSITORY) {
repositoryCount
}
}
The following example shows a custom object called repositories
within a
user
query. It takes a custom object argument of type
RespositoryOrder
that specifies both the field to order by and the direction in
which to order:
...
repositories(orderBy: {field:UPDATED_AT, direction: DESC}) {
...
This snippet is from a larger query that will be explored in more detail later in this topic. The point is, that GraphQL enables APIs to support very complex querying capabilities in arguments.
Nested Objects
So far, you have a very simple query that gets 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, you
will use the relatedTopics
object to get a list of topics related to "GraphQL"
within GitHub:
{
topic(name:"graphql") {
stargazerCount
relatedTopics {
name
stargazerCount
}
}
}
You must specify the object and the fields within that object that you want to retrieve. In this
case, relatedTopics
did not require an argument. However, if you look at the docs,
you'll see that it does have an optional argument (first
) that defaults to
3
, meaning it will only send the first three results. Let's define that to return
10
(the maximum the API allows):
{
topic(name:"graphql") {
stargazerCount
relatedTopics(first: 10) {
name
stargazerCount
}
}
}
This shows that you can specify arguments both on the primary query and on nested object queries, as defined by the schema.
Aliases
Now imagine that you want to get the stargazer count for both GraphQL and JavaScript in a single request. You might try something like this:
{
topic(name: "graphql") {
stargazerCount
}
topic(name: "javascript") {
stargazerCount
}
}
That results in an error because you defined conflicting queries in a single request. To solve this, use an alias on each of the queries:
{
graphql:topic(name: "graphql") {
stargazerCount
}
javascript:topic(name: "javascript") {
stargazerCount
}
}
This returns a response containing the aliases you specified:
{
"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 modify this query to get more than just the stargazerCount
. To avoid
writing code for each aliased query, you can use fragments which represent reusable pieces of query
code. For example, instead of writing this:
{
graphql:topic(name:"graphql") {
stargazerCount
relatedTopics(first: 10) {
name
stargazerCount
}
}
javascript:topic(name:"javascript") {
stargazerCount
relatedTopics(first: 10) {
name
stargazerCount
}
}
}
You can encapsulate the reusable code in a fragment
like this:
{
graphql:topic(name:"graphql") {
...topicDetails
}
javascript:topic(name:"javascript") {
...topicDetails
}
}
fragment topicDetails on Topic {
stargazerCount
relatedTopics(first: 10) {
name
stargazerCount
}
}
You define the fragment by specifying fragment
followed by a name
(topicDetails
in this case) and its type (Topic
in this case) for
validation purposes.
Then, you can reuse the fragment by referencing its name, prefixed by three dots
(...topicDetails
in this case) wherever you need to reuse it. While this example
doesn't save a lot of code, it can be particularly useful when you find yourself repeating large
chunks of code in a complex query.
Variables
Imagine you want to create a query that gets the user profile information and recent repositories for a user. This wouldn't work if you had to pass a hard-coded user string. Instead, GraphQL enables you to define a variable and then pass in a variables object to the query to populate the variables.
First, let's look at the query. This query basically gives you everything you might want to know to construct a profile page for a GitHub user (perhaps for a developer portfolio home page or something):
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
}
}
}
}
}
Up until now, you have been using an anonymous operation (i.e., wrapping the query in curly
braces). Best practice says you should define the operation type and name. In this case, the
operation type is a query
and the name is GitHubUserProfile
. There
are other operation types such as a mutation (modifies data on the server) and a subscription
(subscribes to updates to changes from the server).
You 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, you now
reference the $username
variable as the value for the login
argument.
To specify that argument, you must pass in a JSON object containing a value for
username
. You can do that in GraphQL Playground via the Variables tab at the
bottom left of the application:

Supply a GitHub username:
{
"username": "remotesynth"
}
You can see the result of running the query on the right.
Learn more
Visit the following resources for more information on creating GraphQL queries:
- Queries and Mutations on graphql.org
- Understanding Queries in GraphQL by Peter Ekene
- GraphQL Core Concepts on howtographql.com