GraphQL for Drupalers - part 4 - fetching the entities

GraphQL is becoming more and more popular every day. Now that we have a beta release of the GraphQL module (mainly sponsored and developed by Amazee Labs) it's easy to turn Drupal into a first-class GraphQL server. In this series, we'll try to provide an overview of its features and see how they translate to Drupal.

Logo Drupal/GraphQL

In the last post we talked about the basic building blocks of every GraphQL query - the fields. We've discussed their types and traits as well as described the rules according to which Drupal fields turn into GraphQL fields. This week we were going to expand the topic further and cover field creation, but Daniel Noyola asked an interesting question in the comment below one of the recent articles:

How can I filter the results in a nodeQuery? Like I would in a normal View or with the "where" clause in a SQL Statement. I noticed that it receives a NodeQueryFilterInput but I don't see how to use it.

Fetching entities based on a filter or a set of filters is a common use case, so let's focus on that first.

TL;DR

There are two ways to query the entity repository. First one would be through the entityQuery fields which are shipped with the core module but are limited in functionality. They only allow us to filter by base fields and there's no way to use an operator other than equals to. The other approach is much more powerful, as it's based on Views. It requires an additional module - graphql_views - to be installed though. Let's start with the built-in way.

The nodeQuery

OUTDATED: This section is outdated, since filtering entities changed significantly. Please refer to the documentation on entity filtering with GraphQL.

Each entity type in the system gets its own query field. Let's see in the explorer how it looks like for nodes:

The nodeQuery signature

So it's a field (blue) with 3 arguments: offset, limit and filter (purple) which returns a value of type EntityQueryResult (all types are in yellow).

The first two arguments, offset and limit, are for paging and they work the same way as in SQL. Both are integers and both have default values of 0 and 10 respectively (green). Arguments that have default values can be omitted. We'll use this feature in a while.

The last argument - filter - is of a complex type NodeQueryFilterInput. Let's click it:

NodeQueryFilterInput fields

So it comprises all the base fields of the entity type that is being queried. It's not enough to issue arbitrary queries but it will suffice for a simple use case. This is how we could fetch a list of articles created by a given user:

We haven't specified the offset nor the limit, so they'll get their default values. It means that the output will contain at most 10 results, starting from the result number 0.

That's cool, but what if we wanted to order the articles by node id (nid) to only show the latest articles? Or filter by tags? Or fetch the title text of an image that is attached to a media entity that is connected with the first event that starts after the article's release date?

Use The Views

The answer is: we can do it like we'd normally do it in Drupal - with a view. Views integration has been moved to a separate project, so it has to be downloaded with composer (composer require drupal/graphql_views), from drupal.org or from github.

With graphql_views enabled we can add a GraphQL display to any view in the system.

Adding GraphQL display to a view

Now we can sort the results, filter based on content fields and add relationships. We also have the option to return either the full entities, just a selection of fields, or even search results taken straight from a search server.

Row type options for userArticles view

Contextual filters set in the view will automatically turn into the arguments of the GraphQL field. Let's see an example:

userArticles field signature

This field represents a simple view showing nodes. It has one contextual filter - Content: Authored by - so the corresponding input type consists of just one field:

contextualFilter type

and its row type is set to Entity (as pictured on the screenshot above), so the result will be of type NodeArticle:

userArticles result type

We can use the filed like this:

Views integration is a pretty broad topic, so in the next post we might try to cover it in more detail. There are quite a few more interesting aspects like sorting, exposed filters, and attaching views to entities, so we'll focus on that in an attempt to fully answer Daniel's question. For those interested in the back-end side of things I'd recommend the great Extending GraphQL series by Philipp Melab. The first post that explains how to create fields is here: Extending GraphQL: Part 1 - Fields.

P.S. GraphQL Views is not stable yet. In fact, two issues were spotted and fixed in the process of writing this article. If you spot a bug please report it on github  or let us know in the #graphql channel at Drupal slack.

Other posts in the series

January 29, 2018
8 Comments

Get our Newsletter

 
 

Comments

Hello my friend,
You have done really a good job to write this blog here for us. Its really helpful and informative. Thank you for sharing your thoughts with us.

By Dharmesh Rawal
9 months ago

Thanks a lot. I'm glad you find it useful :)

By Blazej
8 months ago

These blog posts are fantastic! Would love to see these referenced and teased apart in the docs as well. Keep up the great work!

By Justin Winter
9 months ago

Thanks! Much appreciated :).

By Blazej
8 months ago

Seems like in the current version `nodeQuery.filter` expects `EntityQueryFilterInput`, not `NodeQueryFilterInput`. I'm looking for guidance on how to use this filter.

By Clayton
8 months ago

@Clayton I ran into this too, seems that this was changed in the meantime to better reflect the EntityQuery structure(?)
Anyway you can try something like this (there probably is a more elegant way)
`nodeQuery(filter: {conditions: [{field: "type", value: ["competition"], operator: IN}, {field: "status", value: ["1"], operator: EQUAL}]}) {`

By Enrico
8 months ago

There is recent example about how to use filters in the latest version of the module.

By Walter Jenner
7 months ago

Add new comment

You must have Javascript enabled to use this form.
icon
What is Amazee Labs?