I’m going to assume in reading this you have a fair understanding of GraphQL — if not, Sacha does a pretty good introduction here: https://medium.freecodecamp.org/so-whats-this-graphql-thing-i-keep-hearing-about-baf4d36c20cf

What I want to introduce though is not the fundamentals about how it works or setting up basic queries/mutations/subscriptions, but an architectural pattern that really leverages the expressive power of the language.

It goes like this:

Treat the root queries, mutations, and subscriptions as methods to obtain entrant nodes into a node graph and use an object oriented approach with respect to the nodes themselves. This makes all root Mutations methods that change the topography of the graph and puts all methods which change the data in the nodes themselves on their specific types.

Arbitrary Graph Traversals

GraphQL is uniquely designed for arbitrary graph traversals. Take the data graph below

Basically I have a bunch of User s who each have a number of friends.

For exploring the data graph above, I have the following simple schema

With my resolvers looking like

This is probably one of the more confusing elements of GraphQL, so lets walk through it really quick.

I have in my Schema that the user() query returns a User type. But the type that is returned by my user resolver ( User_DB ) doesn’t have the id or friends field.

This is where GraphQL gets smart on us. Because our schema says that it returns the User type, it finds the User root resolver in order to process the type and return any missing fields.

The object returned by that user() query is then the first argument passed to each of these resolvers which allows us to operate on the object to resolve any unresolved fields. So the id field gets populated simply using the _id field on the database returned object. Even better though, we can take those friendIds returned and turn that into actual User objects by retrieving them from the database in the friends resolver.

Holy Moly! I now have a recursive loop in there because the friends field returns an array of User s, which get processed by my User resolver. GraphQL only resolves what the client requests. So the client decides the depth of resolution.

So if I have a query that looks like

I’m not going to hit that friends resolver and I’ll just get

Graphically (no pun intended), this looks like

The node returned by my user() query (Derek) is my Entrant into the graph. This becomes more important later.

Because I’ve set it up to resolve the friendIds into User s, I can also do the following

and get

I’ve just done a graph traversal of arbitrary depth. This is significant because we’ve just allowed our client to specify it’s own composition of data without having to know the resulting shape. Graphically, it looks like

Again, the node returned by my user() query (Derek) is my Entrant into the graph and then I traverse to the other connected nodes.

In this example, I have only one type of node, so it’s a little less interesting, but far easier to visualize. This process basically de-normalizes the data from our database.