How To Condense Your GraphQL Queries With the @materializer Directive
Tags: graphql, mysql, discuss, showdev
Published: 2021-03-25 22:43:44

<link rel="canonical" href="https://example.com/wordpress/seo-plugin/" />

_Originally posted on [StepZen](https://stepzen.com/blog/how-to-use-materializer-on-graphql-queries)_

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](https://spec.graphql.org/June2018/#DirectiveDefinition), 


"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:


```graphql
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](https://www.apollographql.com/docs/apollo-server/schema/directives/#default-directives). 

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:

```graphql
{
  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](https://www.graphql-tools.com/docs/resolvers/):
```graphql
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.
```graphql
  @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](https://stepzen.com/blog/build-your-first-graphql-api).

Want to know more about connecting backends in general? [See our docs](https://my.stepzen.com/docs/build-a-graphql-endpoint/general).