Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dataloader loading incorrect association when struct Id is null #172

Open
arunr14 opened this issue May 23, 2024 · 2 comments
Open

Dataloader loading incorrect association when struct Id is null #172

arunr14 opened this issue May 23, 2024 · 2 comments

Comments

@arunr14
Copy link

arunr14 commented May 23, 2024

Encountered a scenario where dataloader is associating the incorrect child object to a parent object. I was able to work around it by explicitly specifying the foreign key relationship in the resolver.

Environment

  • Elixir version : Elixir 1.16.2 (compiled with Erlang/OTP 26)
  • Absinthe version: Absinthe 1.6.8
  • Client Framework and version : Apollo

ISSUE

I have a graphql object called task with a field checklist that is resolved using dataloader. I have two ecto schemas called task and recurringTask with both of them having a field checklist_id. I have a custom resolver that queries both tables, combines the data and returns a struct %task{ :id, :recurring_id, :checklist_id}. In the returned list, it is possible for some entries to have id = null. When this happens dataloader associates the entry with and incorrect checklist object i.e. task.checklist_id != task.checklist.id. Other entries in the list have task.checklist_id = task.checklist.id as expected. However, for entries with id = null dataloader seems to associate a random checklist object from the ones it has fetched.

I was able to workaround this issue by explicitly specifying the foreign key in the resolver.

Schema/Code

ECTO schema

schema "tasks" do
   <other fields>
    belongs_to :checklist, Tasks.Checklist
    
schema "recurring_tasks" do
    <other fields>
    belongs_to :checklist, Tasks.Checklist

GRAPH QL Definitions

field :tasks, non_null_list(:task) do
      resolve &Queries.list_tasks/3
end
object :task do
    ecto_fields Tasks.Task
    field :checklist, :checklist, resolve: dataloader(Tasks)
end

WORKAROUND:

object :task do
    ecto_fields Tasks.Task
    field :checklist, :checklist, resolve: fn parent, _, %{context: %{loader: loader}} -> 
      loader
      |> Dataloader.load(Tasks, {:one, Tasks.Checklist}, id: parent.checklist_id)
      |> on_load(fn loader ->
        loader
        |> Dataloader.get(Tasks, {:one, Tasks.Checklist}, id: parent.checklist_id)
        |> (&{:ok, &1}).()
    end)
  end
end
@fuelen
Copy link
Contributor

fuelen commented Aug 2, 2024

I noticed the same is true when the struct doesn't even have an ID.

@fuelen
Copy link
Contributor

fuelen commented Aug 2, 2024

If having a primary key is a strong requirement, then dataloader must early raise an exception.
Or generate an internal ID by itself

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants