GraphQL one to many performance issue and limitation

Viewed 215

I have a DB with 2 tables => Player (10k entries) and Goal (100k entries). I have a relationship one to many between them (Player has many Goals)

@Entity()
@ObjectType()
class Player {
  @Field(() => ID)
  @PrimaryGeneratedColumn("uuid")
  id: string;

  @Field(() => [Goal])
  @OneToMany(
    () => Goal,
    goal => goal.player
  )
  goals: Goal[];
  ...
}

@Entity()
@ObjectType()
class Goal {
  @Field(() => ID)
  @PrimaryGeneratedColumn("uuid")
  id: string;

  @ManyToOne(
    () => Player,
    player => player.id
  )
  player: Player;
  ...
}

I want to query players and their goals in order to display players rankings in my client app

query scorers{
  players{
    id
    totalGoals
  }
}

Player resolver looks like this

@Resolver(Player)
class PlayerResolver {
  @Query(() => [Player])
  async players() {
    return this.playerRepository.createQueryBuilder("player").getMany();
  }
  @FieldResolver()
  async totalGoals(@Root() player: Player) {
    return this.goalRepository.count({ player });
  }
}

This is not performant because it creates a SQL query behind the scene to request the goals for every Player. So it's potentially 10k queries. Is it the best strategy to do this? Also I'm wondering how I could possibly order the players by goals count. I'm using type-graphql and typeorm.

1 Answers

You can either try to build the query with join ahead of time (on query resolver level, using @Info to read requested fields) or use a DataLoader library to batch the queries and solve the N + 1 problem.

Related