I'm having some trouble resolving a specific situation which results in performances reduction. I'm quite sure that is something which can be done, but I can't figure oute how to do it.
Here's an example schema for exposing the problem:
type Answer{
answerId: String!
text: String!
topic: Topic!
}
type Topic {
topicId: String!
name: String!
level: Int!
}
extend type Query {
answer(answerId: String!): Answer!
answers: [Answer!]!
}
I've followed the documentation, expecially this part https://gqlgen.com/getting-started/#dont-eagerly-fetch-the-user From my schema, It generates the following resolvers:
func (r *queryResolver) Answer(ctx context.Context, answerId string) (*models.Answer, error) {
...
#Single Query which retrives single record of Answer from DB.
#Fills a model Answer with the Id and the text
#Proceeds by calling the Topic resolver
...
}
func (r *queryResolver) Answers(ctx context.Context) ([]*models.Answer, error) {
...
#Single Query which retrives list of Answers from DB
#Fills a list of model Answer with the Id and the text
-->#For each element of that list, it calls the Topic resolver
...
}
func (r *answerResolver) Topic(ctx context.Context, obj *models.Answer) (*models.Topic, error) {
...
#Single Query which retrives single record of Topic from DB
#Return a model Topic with id, name and level
...
}
When the answer query gets called with answerId parameter, the answer resolvers gets triggered, it resolves the text property and calls the Topic resolver.
The Topic resolver works as expected, retrives a Topic it merges it inside the Answer and return.
When the answers query gets called without answerId parameter, the answer resolvers gets triggered, it retrives a list of answers with a single query.
Then, for each element of that list , it calls the Topic resolver.
The Topic retrives a Topic and it merges it inside the single Answer and return.
The results it's ok in both cases, but the answers query as a performance problem if I'm asking for a lot of Answers.
For each of the answer, the Topic resolver gets triggered and performs a query to retrive a single record.
Ex. If I've 2 Answers --> 1 Query for [Answer0, Answer1], then 1 Query for Topic0 and 1 for Topic1
Ex. 10 Answers --> 1 for [Answer0, ..., Answer9] and then 10 for each TopicN
I would like to obtain some topic array resolver like
func (r *answersResolver) Topics(ctx context.Context, obj *[]models.Answer) (*[]models.Topic, error) {
...
#Single Query which retrives list of Topics from DB
#Return a list of model Topic with id, name and level
...
}
And I expect every element of the returned array to merge with the corresponding element of the Answers array.
Is it possible in some way? Where I can find an example of such approach? Thanks
The problem could be solved using Dataloaders (docs)
I had to implement the following datasource for
Topics: