I am writing a backend application that uses type-graphql. The GraphQL schema includes a Folder
type that looks like this:
type Folder {
id: ID!
name: String!
rules: [Rule!]!
parent: Group
}
Rule
and Group
are other types.
My Resolver defines a Query called folders
that returns all Folders:
import {Query, Resolver} from 'type-graphql'
@Resolver(() => Folder)
export default class FolderResolver {
@Query(() => [Folder])
folders(): Promise<Folder[]> {
// query db and return results
}
}
To query the folders, their rules, and their parent group from the database, I have to join the database tables and return the joined result, which works without problems. However: If the rules
field and / or the parent
field was not requested in the GraphQL query, I could omit the joins and make the database query much more efficient. So the fields that were requested in the GraphQL query have a definite effect on the logic that I need to execute, but I don't see a way of finding out which fields were requested inside the folders
function.
When a Query in a type-graphql Resolver is executed, is there a way to determine which fields were requested in the GraphQL query?
Have a look at Field Resolver. The annotation is specifically made for such purpose
import {Query, Resolver, FieldResolver} from 'type-graphql'
@Resolver(() => Folder)
export default class FolderResolver {
@FieldResolver()
rules(@Root() folder: Folder) {
// ...
}
@FieldResolver()
parent(@Root() folder: Folder) {
// ...
}
@Query(() => [Folder])
folders(): Promise<Folder[]> {
// query db and return results
}
}
Now, when a user requests a query without rules
or parent
as a part of their attributes, they won't be called, if they do either or both will be called. Your logic to fetch data for them resides in their own field resolvers.
Updated as per comment:
If you have to get fields queries by the clients, you may use a library like graphql-fields. This helps you to extracts fields from the info
parameter of the resolver function. Something like this: (as mentioned in the docs)
import graphqlFields from 'graphql-fields';
@Query(() => [Folder])
folders(@Info() info: GraphQLResolveInfo): Promise<Folder[]> {
// get fields
const topLevelFields = Object.keys(graphqlFields(info));
// query db and return results
}
Now you can run your query based on the requested fields.