How To Condense Your GraphQL Queries With the @materializer Directive
Let's start by understanding our context. StepZen's @materializer
is a custom GraphQL directive, but what's a graphQL directive?
As the GraphQL specs tell us,
"A GraphQL schema describes directives which are used to annotate various parts of a GraphQL document as an indicator that they should be evaluated differently by a validator, executor, or client tool such as a code generator."
Basically, this means that we can change what we get back from our queries based on what's in the schema, but this will make more sense with an example. Let's look at the @skip
directive. It's used only in GraphQL operations:
query yellowQuery($isCerulean: Boolean) {
yellowField @skip(if: $isCerulean)
}
In this example, yellowField
is returned when $isCerulean
is false.
Core specs vs. custom
@skip
is one of just three default directives defined in the GraphQL spec. @include
and @deprecated
are also default.
StepZen's @materializer
is a custom directive, in this case made by StepZen. So why did we make it?
@materializer
reduces the code you need to write
Say we had a database with two tables, genus
and species
, and we wanted to make a query like:
{
species(name: "p. tigris") {
name
discoveredDate
genus {
name
isLethal
}
}
}
This means we're grabbing code from both tables, based on a species_id
row in our database. How are we going to implement this?
What you would have to write without @materializer
Without the @materializer
directive, you have to write your own resolverMap:
const resolver = {
Query: {
genus(parent, args, context, info) {
if (!args) return new Error('missing species_id');
return genus.find(genus => genus.id === args.id);
}
}
};
Already you've had to construct logic to pick out the right genus, as well as think through how you'll handle errors.
But what if your data was coming from two different backends-- say, the genus from a MySQL database and the species from an API. You'd have to write resolvers to combine the data yourself. That's a lot of work.
The amount of code you write with @materializer
Here, name
is the argument and field
is how @materializer
will fill it.
@materializer(
query: "genus"
arguments: [{ name: "id" field: "genusID"}]
)
Pop it in at the end of your type extension, and you're done! @materializer
combines your data from your two types for you, even if the types are requesting the data from two different sources.
So much simpler than writing your own resolvers.
Where do we go from here?
Curious about how to build a GraphQL API that connects to a MySQL database with StepZen? Try this blog post out.
Want to know more about connecting backends in general? See our docs.