Hacker News new | ask | show | jobs
by xtrumanx 3905 days ago
I'm a big fan of React but it took me a year after its introduction for me to get it and like it. What particularly did the trick for me was one of Pete Hunt's talks he gave a year after release acknowledging the confusion and explaining the reasoning for React rather than just the technology itself.

I feel like GraphQL can be something great and the pain points they identify with typical APIs are stuff I've felt but GraphQL just feels incomplete to me. I feel they're focusing too much on what GraphQL looks like on the client-side and not enough what it looks like on the server-side. The biggest question I have is what's going to process the GraphQL query on the server to fetch the data from the actual datastore? What does that look like when working with typical datastore such as a SQL-based database? The closest thing I've seen that answered that question was this blog post[0] which doesn't look very appealing if that's what the server-side implementation is going to look like. The blog post's implementation looks like a more complicated version of my own APIs which are usually a series of custom endpoints based on my client's needs. I don't see the big deal right now. Maybe next year...

[0] https://medium.com/@clayallsopp/your-first-graphql-server-3c...

5 comments

I found this example in the dataloader README useful, as it deals with loading from a SQL-based database, with relationships, which is similar to the first project I'm planning on trying it with:

https://github.com/facebook/dataloader#using-with-graphql

Check this out if you understand scala:

https://github.com/sangria-graphql/sangria-akka-http-example

Pulling data from a datastore is up to you. You can use whatever library you like to pull data in. All you have to do is make your `resolve` methods just return the data.

The GraphQL schema definition is basically an adapter (as in adapter pattern) on top of your datastore(s).

GraphQL means UI components can stand on their own - they work without custom endpoints. And it's faster. You do need to write an adapter between GraphQL and your datastore, which is probably hard today, and probably easier next year, but you only need to pay that cost once.
I wrote a blog post yesterday that covers a bit of how we're using GraphQL at my day job. [0]

[0] https://blog.jacobwgillespie.com/from-rest-to-graphql-b4e95e...

> The biggest question I have is what's going to process the GraphQL query on the server

It's really not much different from processing a REST-based API request. In theory, you could parse the request and then just execute the necessary SQL to fill out the result.

However, what Facebook's GraphQL library lets you do is define a schema that specifies how each piece of the result is fetched. It's like a declarative API builder. ("GraphQL" is a huge misnomer; it's neither graph-query-oriented, nor is it a query language — it's a protocol.) GraphQL-the-language doesn't make much sense until you look GraphQL-the-library and understand its design.

For example, let's say the GraphQL query is:

  query {
    story(id: "1") {
      text
    }
  }
Your schema might be declared like this:

  const storyType = new GraphQLObjectType({
    name: 'Story',
    description: 'A story.',
    fields() {
      id: {
        type: new GraphQLNonNull(GraphQLString),
        description: 'The ID.',
      },
      text: {
        type: GraphQLString,
        description: 'The text.',
      }
    }
  });

  const queryType = new GraphQLObjectType({
    name: 'Query',
    fields() {
      story: {
        type: storyType,
        args: {
          id: {
            description: 'ID of the story to fetch',
            type: new GraphQLNonNull(GraphQLString)
          }
        },
        resolve(root, {id}) {
          return SQLDatabase.findStoryById(id)
        }
      }
    }
  });
You declare static fields as well as resolver functions that take arguments and are expected to furnish the query with the actual results. You then "execute" the query, which will cause the resolver's to run as they are triggered by parts of the query. For example, if the storyType contains resolvers, any nested queries will invoke them.

I recommend looking at the tests [2] in the GraphQL JS library, because they show some useful examples. There's already a Ruby [1] library for declaring schemas in the same way.

If you're doing SQL underneath, optimizing a GraphQL query into the fewest possible SQL queries might be tricky. For example, let's say each story has an author; doing an author query per story isn't going to cut it; you're going to want to join the authors table. But the outer queryType doesn't know if the query will be asking for the authors. I don't know if the library provides any way to solve this yet.

[1] https://github.com/rmosolgo/graphql-ruby

[2] https://github.com/graphql/graphql-js/tree/master/src/__test...