absinthe-graphql / dataloader

DataLoader for Elixir
MIT License
489 stars 99 forks source link

Dataloader queries assoc even if already loaded #164

Closed thojanssens closed 1 year ago

thojanssens commented 1 year ago

Say the resolver returns a struct with an assoc that has already been loaded, e.g.

%Organization{
  name: "Acme",
  members: []
}

When using Dataloader with Absinthe to load the :members for the organization, dataloader will still execute a query to fetch the members while it was already loaded (set to []).

I found this old merge: https://github.com/absinthe-graphql/dataloader/issues/18 https://github.com/absinthe-graphql/dataloader/pull/19/files

But it doesn't state why we ignore already preloaded associations. It only mentions consistency but I do not see why we need to execute preload queries again if already executed, leading to double db requests.

benwilson512 commented 1 year ago

Hey @thojanssens the issue is that Dataloader has no way of knowing whether the records already loaded match what dataloader would have loaded had it done so itself. Dataloader.Ecto runs the association through the query logic in your source query function, but it has no way of knowing that you've done the same for the values already there.

The way to do this is explicitly use https://hexdocs.pm/dataloader/Dataloader.html#put/5 to set the existing values as the dataloader result. You can see that Absinthe does so here https://github.com/absinthe-graphql/absinthe/blob/v1.7.5/lib/absinthe/resolution/helpers.ex#L348 if you set the use_parent option.