Part 2: Creating A GraphQL Server With Node.js
I hope you are all safe and that this blog finds you in good health ❤️.
In my previous blog, we have learnt about
- Queries in GraphQL
- Arguments in GraphQL
- Query alias in GraphQL
- Variables in GraphQL
If you missed it, please check it out here.
Let’s say our customer base has grown, and our new clients require more information.
For example, the clients want to compare pizzas side-by-side while also looking at the available toppings. This operation would need us to repeat the fields at least once for each comparison.
GraphQL fragments
GraphQL fragments allow us to build sets of fields and then use them in queries as needed. GetPizzas query from the previous lesson. We can refactor it to the following: GetPizzas with a fragment
We can refactor it to the following:
If the fields are repeated, the above query becomes repetitious. Fragments are typically used to break extensive application data requirements into smaller chunks, especially when several UI components with various fragments must be combined into one initial data retrieval.
The fragment is now the only item that has to be updated if any extra fields are added.
Test your GraphQL query with fragments
The response should look like this:
{
"data": {
"Neapolitan": [
{
"id": 1,
"pizza": "Neapolitan Pizza"
}
],
"Chicago": [
{
"id": 2,
"pizza": "Chicago Pizza"
}
]
}
}
Dynamic Query Using Directives
GraphQL directive
In the last lesson, we learned how to utilize GraphQL variables to filter pizzas based on a keyword entered by the user.
Imagine now that our application has grown in popularity. Each pizza now requires a summary and a more thorough description, which also needs additional fields of data. We need a method to dynamically modify the structure and layout of our queries.
GraphQL has a feature called directive that allows this. A directive can be appended to a field or fragment and can influence the query’s execution in any way the server chooses. The GraphQL standard contains two default directives that each GraphQL server implementation must support:
@include(if: Boolean)
: We include this field if the argument is true.@skip(if: Boolean)
: We skip this field if the argument is true.
How to make a dynamic query
You need to do three things:
- Using the previous query as a reference, we need to find fields that are conditionally used. We’ll then decide to load the toppings fields if
withToppings
isTrue
. - We need to define
withToppings
as the variable andBoolean
as the type since the value can only be either true or false. Since it’s mandatory, we also need to remember the exclamation mark (!
). - We need to add directives to the
toppings
fields and remember to pass$withToppings
.
We’re now able to refactor the previous query, reproduced below:
@include(if: Boolean)
Include this field only if the argument is valid.@skip(if: Boolean)
Skip this field if the argument is valid.
We can refactor the query above to the following:
Look at the illustration below to understand the GraphQL query directives.
You should receive a response from the server that looks like this:
{
"data": {
"pizza": {
"id": 1,
"pizza": "Neapolitan Pizza",
"toppings": [
{
"topping": "Cheesy"
}
]
}
}
}
GraphQL mutation
In GraphQL, not every request has side effects on the server. Technically, any query could implement a function to modify server data. However, this is considered bad practice. Any operation that causes write should be sent explicitly via mutation
operation type.
Similar to queries, the mutation field returns an object type. Let’s look at the mutation that’s available on our GraphQL server.
After checking what mutation operation available on your GraphQL server you can now take a look at the fields and arguments to know more about what data to be send to the server.
Your first GraphQL mutation
After determining what operation is available, what fields to expect, and what argument is required, we can now create the CreatePizza
mutation.
Steps to add GraphQL mutation
- Declare the operation type as
mutation
and the operation name asCreatePizza
.
- The
CreatePizza
operation requires[ToppingInput!]!
andPizzaName
as arguments. To do this, add[ToppingInput!]!
as$createPizzaToppings
and$createPizzaName
and make them variables.
- Now, we add
CreatePizza
and map the variable with the required arguments.
- Define all the required fields we want to fetch after the operation.
Look at the illustration to understand the GraphQL mutation.
Run GraphQL mutation on Apollo Studio
Now we can paste the CreatePizza
mutation to the upper-middle section of Apollo Studio. Since we defined variables for our mutation, we need to remember to pass the JSON as variables to the lower-middle column.