How to know which fields were requested in a GraphQL query?
Here, are couple main points that you can use to optimize your queries for performance.
- In your example there would be great help to use https://github.com/facebook/dataloader. If you load comments in your resolvers through data loader you will ensure that these are called just once. This will reduce the number of calls to database significantly as in your query is demonstrated N+1 problem.
- I am not sure what exact information you need to obtain in posts ahead of time, but if you know the post ids you can consider to do a "look ahead" by passing already known ids into comments. This will ensure that you do not need to wait for posts and you will avoid graphql tree calls and you can do resolution of comments without waiting for posts. This is great article for optimizing GraphQL waterfall requests and might you give good idea how to optimize your queries with data loader and do look ahead https://blog.apollographql.com/optimizing-your-graphql-request-waterfalls-7c3f3360b051
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.