graphqlapolloapollo-serverresolver

How to know which fields were requested in a GraphQL query?


I have written a GraphQL query which like the one below:

{
  posts {
    author {
      comments
    }
    comments
  }
}

I want to know how can I get the details about the requested child fields inside the posts resolver.

I want to do it to avoid nested calls of resolvers. I am using ApolloServer's DataSource API.

I can change the API server to get all the data at once.

I am using ApolloServer 2.0 and any other ways of avoiding nested calls are also welcome.


Solution

  • You'll need to parse the info object that's passed to the resolver as its fourth parameter. This is the type for the object:

    type GraphQLResolveInfo = {
      fieldName: string,
      fieldNodes: Array<Field>,
      returnType: GraphQLOutputType,
      parentType: GraphQLCompositeType,
      schema: GraphQLSchema,
      fragments: { [fragmentName: string]: FragmentDefinition },
      rootValue: any,
      operation: OperationDefinition,
      variableValues: { [variableName: string]: any },
    }
    

    You could transverse the AST of the field yourself, but you're probably better off using an existing library. I'd recommend graphql-parse-resolve-info. There's a number of other libraries out there, but graphql-parse-resolve-info is a pretty complete solution and is actually used under the hood by postgraphile. Example usage:

    posts: (parent, args, context, info) => {
      const parsedResolveInfo = parseResolveInfo(info)
      console.log(parsedResolveInfo)
    }
    

    This will log an object along these lines:

    {
      alias: 'posts',
      name: 'posts',
      args: {},
      fieldsByTypeName: {
        Post: {
          author: {
            alias: 'author',
            name: 'author',
            args: {},
            fieldsByTypeName: ...
          }
          comments: {
            alias: 'comments',
            name: 'comments',
            args: {},
            fieldsByTypeName: ...
          }
        }
      }
    }
    

    You can walk through the resulting object and construct your SQL query (or set of API requests, or whatever) accordingly.