Nice article!
Scott Molinari

Whether or not GraphQL is actually a graph query language is kind of a technical question. Yes, GraphQL can be used to query a data system formatted in a graph shape and that is GraphQL’s number 1 use both inside and outside of Facebook (thus the name fits). However, there is technically nothing in the GraphQL specification that requires the use of a graph data structure. Even all the major GraphQL execution engines return a denormalized tree data structure vs. a normalized graph.

Two great examples of GraphQL querying a non-graph are gdom and Gatsby 1.0. The DOM and file system are both trees, and their GraphQL interfaces allow them to be queried and returned as trees.

This loose interpretation of the GraphQL specification is what makes GraphQL such a powerful abstraction. However, I completely agree with Lee that the number one use case for GraphQL is operating on a data graph, and both Apollo Client and Relay operate on GraphQL data as a normalized graph (which is notably a complex problem. It would be easier if GraphQL had more opinions about graphs). While technically there is nothing in the GraphQL specification that warrants using “graph” in the name, in practice data graphs are predominately what GraphQL queries. Also the name TreeQL, while more accurate, just isn’t as attractive 😉

So in practice the statement “GraphQL isn’t a graph query language” may be false because most people use GraphQL as a graph query language, but technically it’s true when we look at the specification.

I wrote an article about this a while ago which could use an update: “The Falcor data model is a graph, and the GraphQL data model is a tree.”

I’m not sure precisely what you mean by multi-dimensionality. A GraphQL connection is a fancier way to model a list which in this case is one-dimensional with the only axis being the array index. Of course, I may be misinterpreting 😊

You could express a graph relationship with “normal” or “flat” pagination in GraphQL by simply documenting that a certain field, say:friends: [Person], contains all of the people that are connected to another person with a friends edge. The reason GraphQL connections are useful is that they:

  1. Provide space to add a cursor which powers the underlying cursor pagination implementation of GraphQL connections.
  2. Provide space to express more information about the graph edge by adding fields like a friendedAt date.

One principle of good GraphQL schema design is to always give yourself more space then you need so that fields may be added in the future (this is something I want to write about in the future).

As for ordering, that is an implementation detail of your pagination system. You could have a GraphQL connection without cursor-based pagination. That is completely possible. Your field would just look like: friendsConnection(limit: Int, offset: Int): FriendsConnection instead of the classic connection field with first, after, etc. In PostGraphQL we provide an enum as the type to an orderBy argument that allows you to specify which column in the database you want to sort on, for instance. In the case of an edge you could sort by a friendedAt date with an orderBy argument, but you would still want to expose that data in some way to the front-end. In that case I would recommend putting it on the edge instead of creating a new type that introduces another level of indirection.

I hope that answers your questions 😊

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.