Open In App

Querying Data with GraphQL

Last Updated : 29 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

GraphQL is an open-source technology that allows us to query only the data that we require, unlike the traditional REST architecture which returns us the entire resources and data with specific endpoints configured for the same. Using GraphQL, we specify using the query the data that we want, and it returns the specified data in the specified format. It helps reduce the amount of data transfer over the network and saves network bandwidth. In this article, we will learn how to Query data using GraphQL.

Anatomy of a GraphQL Query

A GraphQL Query consists of fields that define how the response would look like. The Query is sent to the GraphQL server which returns the response in the required format.

A GraphQL Query schema looks like below

query {
getPokemon(id: "123") {
name
type
weight {
maximum
minimum
}
}
}

Here,

  1. query – It indicates the above operation is a GraphQL Query
  2. getPokemon – It is the root field that suggests to fetch the pokemon data with the given ID
  3. name, type, weight – They are the fields present on the Pokemon data, and are requested to be present in the response.

GraphQL Query Consists of the Following Concepts

1. Fields

They represent a singular piece of data that will be returned in the Query response, and which will be present as a property in the GraphQL Schema type. When a query is executed, the response will include the requested fields for each object returned.

Example: Single Level Basic Querying to get the data of a pokemon named, “pikachu”.

In the below query, we have

  • pokemon – root field of the query that represents the data that the client wants to retrieve from the API.
  • pikachu – argument for the query passed that represents the specific criteria that the user wants the information about
  • name, and id – they represent the fields that are requested by the user to be returned in the response object.
{
pokemon(name: "pikachu") {
name
id
}
}

Output

The output of the above query call will look like below

file

2. Directives

They provide us a way to conditionally include or exclude data from the Query response, based on some conditions.

Example:

In the below query, we have

  • id, and name – they represent the fields that are present in the fragment that is defined on the Pokemon type.
  • retrievePokemon – root field of the query that represents the data that the client wants to retrieve from the API.
  • pikachu – argument for the query passed that represents the specific criteria that the user wants the information about
  • firstPokemon – they represent the aliases that are assigned to the pokemon field of the query, It implies that the data returned by the respective queries will be renamed as firstPokemon, and secondPokemon, respectively.
  • @include – It represents a directive which controls whether to fetch a particular field from the API, depending on the condition passed in its argument.
query retrievePokemon{
firstPokemon: pokemon(name:"pikachu") {
name
id @include(if: false)
}
}

Output:

The output of the above query call will look like below

file

3. Arguments

They are present in the Query and help determine the specific record to fetch from the Database. For example, by providing Id in the argument, we will fetch only the record specific to that Id in the database. They are essentially used to filter the response data returned by the query.

Example

In the below query, we have

  • pokemon – root field of the query that represents the data that the client wants to retrieve from the API.
  • pikachu – argument for the query passed that represents the specific criteria that the user wants the information about
  • name, and id – they represent the fields that are requested by the user to be returned in the response object.
{
pokemon(name: "pikachu") {
name
id
}
}

Output:
The output of the above query call will look like below

file

Nested Queries Retrieving Related Data

With the help of nested queries, we can pull all the related data from a single query, instead of doing multiple queries.

In the below query, we have

  • pokemon – root field of the query that represents the data that the client wants to retrieve from the API.
  • pikachu – argument for the query passed that represents the specific criteria that the user wants the information about
  • name, and id – they represent the fields that are requested by the user to be returned in the response object.
  • types – It represent the nested field that the user wants the information about in the query response object.
  • slot – It represent the selection set, or field for the nested type “types”. This implies that the user only wants the information about the slot of the pokemon from its types.

Example

{
pokemon(name: "pikachu") {
name
id
types {
slot
}
}
}

Output:
The output of the above query call will look like below

file

Aliases Renaming Fields in Responses

With the help of aliases, we can rename the fields on the client side to something other than that which is actually present in the Schema type. This gives us more flexibility to change the response data without changing the schema itself.

Example

In the below query, we have

  • retrievePokemon – root field of the query that represents the data that the client wants to retrieve from the API.
  • pikachu, and charizard – argument for the query passed that represents the specific criteria that the user wants the information about
  • id – they represent the fields that are requested by the user to be returned in the response object.
  • firstPokemon, and secondPokemon – they represent the aliases that are assigned to the pokemon field of the query, It implies that the data returned by the respective queries will be renamed as firstPokemon, and secondPokemon, respectively.
query retrievePokemon{
firstPokemon: pokemon(name:"pikachu") {
id
}
secondPokemon: pokemon(name:"charizard") {
id
}
}

Output:

The output of the above query call will look like below

file

Fragments Reusable Query Components

They are the reusable components of a query, which can be reused at multiple places. They need to defined once in the file. This helps us in cases where we have a complex query, and we want to declare it only once, so we can reuse it at multiple places in the code.

Example

In the below query, we have

  • basicInfoOfPokemon – It represents a fragment that is defined on the Pokemon type. It determines which fields to include from the Pokemon type.
  • id, and name – they represent the fields that are present in the fragment that is defined on the Pokemon type.
  • retrievePokemon – root field of the query that represents the data that the client wants to retrieve from the API.
  • pikachu – argument for the query passed that represents the specific criteria that the user wants the information about
  • firstPokemon – they represent the aliases that are assigned to the pokemon field of the query, It implies that the data returned by the respective queries will be renamed as firstPokemon, and secondPokemon, respectively.
fragment basicInfoOfPokemon on Pokemon {
name
id
}

query retrievePokemon{
firstPokemon: pokemon(name:"pikachu") {
...basicInfoOfPokemon
}
}

Output:

The output of the above query call will look like below

file

Query Variables Parameterizing Queries

With the help of variables, we can parameterize our queries and declare or initialize them in our queries to be later used as a placeholder for dynamic values inside the query body.

Example

In the below query, we have

  • id, and name – they represent the fields that are present in the fragment that is defined on the Pokemon type.
  • getPokemon – root field of the query that represents the data that the client wants to retrieve from the API.
  • pokemonId – It represents a Query variable that imply that pokemonId will be passed in the query, and then we can reuse the pokemonId as the query argument to fetch and filter the results on the basis of it.
query ($pokemonId: ID!) {
getPokemon(id: $pokemonId) {
id
name
}
}

Conclusion

In this article, we learned how to query or fetch data using GraphQL endpoints, and learned about the basic concepts of GraphQL queries, including fields that define what data we want to receive from the server, arguments for retrieving the data having a specific id, aliases to rename the response data for simplicity and to avoid naming conflicts, fragments to define the reusable pieces of code in the query, and directives to apply conditional rules to the data to be fetched from the server.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads