Alexander Kondov

@KondovAlexander

Advanced querying with GraphQL and Express

This is the second part of my article series on GraphQL Basics. If you haven’t read the previous part you can catch up here.

Last time we finished setting up our basic GraphQL server with Node and Express. We explained why GraphQL exists and what purpose it has, we went through the installation and the basic setup and finished with our first actual query.

We’ve learned a lot, but we haven’t done anything practical yet. The feeling of accomplishment when you successfully run a GQL query is great, but it’s power is shown when it comes to more advanced operations. In this article we will look at query parameters and nested queries.

Query parameters

We’ll start by figuring out how to use query parameters and fetch a single entity off our service. In order to fetch data structured in a different manner we will need to add a new field to our RootQuery. We cannot reuse the posts field that we have for the single post because GraphQL expects it’s type to be a list. But fetching a single item will most likely return an object.

This empowers the users of our GraphQL server to write even more powerful and verbose queries. We will use the post keyword to register the single post query endpoint. This way anyone looking at our code will know what to expect out of the GQL server depending if the noun is in singular or plural.

The differences are in the type and the args properties. In order for GraphQL to understand what it will receive as params we need to tell it what type they will be. Each of the arguments will be represented as an object with a type. As you can guess GraphQL’s got it’s own magical types that we need to use here. Let’s add two more properties in the destructured list in the beginning of the file.

const {
...
GraphQLNonNull,
GraphQLID
} = graphql

I’ve added only the ones we are currently importing to keep the snippet small. With them we will tell GraphQL that the id property is required (we can’t really fetch a post without an ID) and that it should be of type ID.

After that, properties passed in the query will be available to us from the args object in the resolve function. Disregard the parentValue field for now, we’ll discuss it later in the article. Everything else is straight forward — we will use the passed property to query the service for the given post. Because we are again using the post type we needn’t worry about specifying the type fields again. This is how the finished field will look in the RootQuery

In the fetch call I’m using some ES6 wizardry and placing the arguments directly in the strict. Now you can refresh your server (if you’re not using nodemon, which I highly recommend) and run a single post query from the graphical interface.

If everything is done correctly we should see a response containing the data for a single post. Congratulations, this is our first query using parameters!

Something interesting to note here is the documentation that GraphQL will automatically create for you. If you look at the right column in the graphical interface you will see a link for the RootQuery. If you click on it you will see all the registered fields that you can query together with their allowed arguments.

Nested queries

The next scenario that we will look at is a bit more complicated. Here we will venture into the depths of GraphQL and explore it’s powers. We will learn how to fetch related data by representing it as a nested object inside it’s parent.

Thankfully, the service we picked to play with also provides comments to the posts. Sadly, you can only get one entity per request. Meaning that our service allows us to fetch only post info or only comments with a single request. This is an excellent example of how we will cover this behaviour behind GraphQL’s curtain and fetch everything we need with a single GQL query!

We will start by defining a new type — a CommentType.

Make sure to create it before the PostType because we will need to reference it there. Once we have it defined, we will need to add a new field on the PostType. This is because by nesting the comments inside of the PostType, GraphQL will consider it a field.

You have probably noticed that when it comes to fetching resources this is usually done via the resolve function. This is what we did for the post list, for the single post and this is what we will be doing for the comments.

As we mentioned in the previous article, GraphQL acts as a wrapper around the services you use, so in the current case, if we want to fetch posts with their comments we will need to make the two separate requests — GraphQL cannot help us with that. It does however keep the API of the person making the request incredibly clean and simple.

With that in mind let’s now define our comments field with a resolve function inside of it to fetch our comments.

Here we will finally use the parentValue property. You will see in a bit that comments are actually a query on their own, so they need to be passed the post id in some way. This is done with the parentValue — it will contain the arguments that are passed to it’s parent query.

In this situation we can use it to get the id of the post and send a second request to fetch the comments. The result will be an object containing the post information and a list of comments with the fields that we need from it.

You can imagine that it would be a lot easier and intuitive for your front end developer to fetch data like this. Your FE team won’t have to know what service to use or where to fetch data from, since the GraphQL server will serve as a gatekeeper.

Wrap up & What’s next

So far we’ve learned how to set up a GraphQL server from scratch and how to query data from it. We also know how to pass parameters and use nested queries. However, there is one big point that we haven’t covered so far and that is posting to GraphQL.

We’ve only been fetching data but at some point we would also like to push data. In the next article we will be focusing on that!

Thank you if you’ve read this far. If you enjoyed the article please hold the clap button. Any feedback is much appreciated, I respond to everyone!

More by Alexander Kondov

Topics of interest

More Related Stories