Costly nested resolvers

Hi all,

I face some performance issues linked to a costly nested resolver.

I have a GQL endpoint that roughly looks as follows

type Query {
  foos(): [Foo!]!
}

type Foo {
  id: ID!
  fieldA: string
  fieldB(input: Object): [Int!]! # Uses info from Foo + input to run an SQL query
}
// simplified resolver
const FooResolvers: Resolvers = {
  Query: {
    foos: async (
      _parent,
      args: QueryFooArgs,
      context: Context,
      info: GraphQLResolveInfo
    ): Promise<GQLFoo[]> => {
      return sql.fetchFoos(); // fieldB === undefined
   }
},
Foo: fieldB: async (
      parent: GQLFoo,
      args: FooFieldBArgs,
      context: Context
    ): Promise<FieldB> => {
      return sql.groupByAndSum(args.input, parent.id);
    },

I have a nested resolved for fieldB which works fine.

  1. I fetch all Foos in the foos() query resolver, and then
  2. in the Foo::fieldB nested resolver, I use the Foo details + fieldB’s input to produce fieldB. However, it’s a relatively complex aggregation that requires a read on my database.

Given that foos() returns an array of Foo, which can grow relatively large, I would rather not do N individual requests to my DB.

For something like fieldA, even if it needed some computation, I know that I can access the field list in the top query resolver by using info.fieldNodes[0]?.selectionSet. However, it seems slightly more complicated, and way less reliable for fieldB, since it has argument in the form of an object.

My questions are:

  1. This generally seems like an anti-pattern. Is there a better way to batch my nested resolvers?
  2. Is there a proper way to access my nested resolver’s arguments from the top query?

Thanks in advance!