GraphQL queries with tables join using Node.js

itaied picture itaied · Dec 3, 2016 · Viewed 24.2k times · Source

I am learning GraphQL so I built a little project. Let's say I have 2 models, User and Comment.

const Comment = Model.define('Comment', {
  content: {
    type: DataType.TEXT,
    allowNull: false,
    validate: {
      notEmpty: true,
    },
  },
});

const User = Model.define('User', {
  name: {
    type: DataType.STRING,
    allowNull: false,
    validate: {
      notEmpty: true,
    },
  },
  phone: DataType.STRING,
  picture: DataType.STRING,
});

The relations are one-to-many, where a user can have many comments.
I have built the schema like this:

const UserType = new GraphQLObjectType({
  name: 'User',
  fields: () => ({
    id: {
      type: GraphQLString
    },
    name: {
      type: GraphQLString
    },
    phone: {
      type: GraphQLString
    },
    comments: {
      type: new GraphQLList(CommentType),
      resolve: user => user.getComments()
    }
  })
});

And the query:

const user = {
  type: UserType,
  args: {
    id: {
      type: new GraphQLNonNull(GraphQLString)
    }
  },
  resolve(_, {id}) => User.findById(id)
};

Executing the query for a user and his comments is done with 1 request, like so:

{
  User(id:"1"){
    Comments{
      content
    }
  }
}

As I understand, the client will get the results using 1 query, this is the benefit using GraphQL. But the server will execute 2 queries, one for the user and another one for his comments.

My question is, what are the best practices for building the GraphQL schema and types and combining join between tables, so that the server could also execute the query with 1 request?

Answer

marktani picture marktani · Dec 14, 2016

The concept you are refering to is called batching. There are several libraries out there that offer this. For example:

  • Dataloader: generic utility maintained by Facebook that provides "a consistent API over various backends and reduce requests to those backends via batching and caching"

  • join-monster: "A GraphQL-to-SQL query execution layer for batch data fetching."