Is there a library that, say for Golang, helps translate a GraphQL Query into SQL statements to actually get the data?
Is there a library that, say for Golang, helps translate a GraphQL Query into SQL statements to actually get the data?
There are a couple approaches I've seen for mapping to an SQL backend.
One is batching - You get the top level resources, then save their accosted record IDs until later so you can make fewer calls to get their associations. This still makes quite a few database calls, especially for deeper queries or many different type of objects.
Another approach is "whole tree up-front" where you take the AST of the graph you're trying to resolve, and convert that to one big SQL query that joins all the associated objects. This can be more performant in some situations as it only makes a single database query, but a drawback is that larger queries eat up a more bandwidth from your query since having many joins causes data duplication. Another drawback is that having a single query makes it so you can't cache each resolver individually like you might be able to do with a batching solution.
I don't have all my links handy but here's one you can check out: https://github.com/facebook/dataloader
If anyone has something to add please chime in! I'd love to hear how people are really using GraphQL with SQL backends!
We run our API at http://www.cargosense.com/ entirely via GraphQL over quite a lot of postgres tables and this has remained very performant for us. Elixir makes it easy to do concurrent batched requests, as well as in memory caches that live for either the duration of the request or long as desired.
For some particularly complicated cases we have a materialized view, but this is largely used to power a reporting service that builds snapshots from this.
Any questions you have in particular?
It might appear verbose at first, with it needing exported method names all over the place, but I've grown accustomed to it now. The repo has a full star wars example which helped me to get oriented quickly.
Otherwise it depends on your GraphQL implementation and what DB adapters or ORMs they support. For example, `graphql-ruby` includes a generator for a Rails-compatible GraphQL schema.
Anyone care to comment from practical experience?
Most of the resolvers end up looking something like
{
type: FooType,
args: {
fooId: GraphQLString,
...paginate.args,
},
resolver: createRESTResolver(
({ fooId }) => [`${services.foo}/:fooId`, { fooId }]
).use(paginate),
}
but if I was doing it again I'd probably abstract the creation of the entire field rather than just the resolver.https://github.com/stems/join-monster (1 query, overhead for more than 2 levels)
https://github.com/facebook/dataloader (best case, 1 query per level, in sequence )
resolve (root, args) { return Db.models.post.findAll({ where: args }); }
(sorry for the lack of markup, I don't know how to do anything here yet)
Here's a blog post specifically for Golang: http://alexandrutopliceanu.ro/post/graphql-with-go-and-postg...