dantswain
This is a sort of convoluted model that I didn’t have much control over. I’ll try to explain in words what’s happening and then provide a distilled-down example of the code.
I have a model, A, with a many-to-many relationship to another model, B. Model B has a many-to-many self-referencing relationship with itself (I didn’t design the schema…
). I also have a “bulk loading” query that, given several ids for A, should load those As and preload their Bs and the child Bs. This works fine if I give the query a single A id, but if I give it multiple ids, the query results only have one of the As associations loaded.
The models look like this:
defmodule A do
use MyApp.Web, :model
schema "a" do
many_to_many(:bs, B, join_through: "a_bs")
end
end
defmodule B do
use MyApp.Web, :model
schema "b" do
field :parent_id, :integer
has_many(:children, B, foreign_key: :parent_id)
end
end
defmodule A.Query do
import Ecto.Query
alias MyApp.Repo
# there's some subtlety here in how my actual (much more complex) query is written that I'm
# trying to preserve
def bulk_load(ids) do
as_query()
|> where([a], a.id in ^ids)
|> Repo.all
|> Repo.preload([
bs: bs_query()
])
end
defp as_query do
from a in A, select struct(a, [:id])
end
def bs_query do
from b in B,
left_join: children in assoc(b, :children),
preload: [children: children],
select: struct([:id, {:children, [:id]}])
end
end
Then, supposing I have two A with ids 1 and 2, both associated with a B having id 1 and no children, The results look like:
# individual queries work as expected
A.Query.bulk_load([1])
=> [%A{id: 1, bs: [%B{id: 1, children: []}]}]
A.Query.bulk_load([2])
=> [%A{id: 2, bs: [%B{id: 1, children: []}]}]
# query with multiple ids only populates bs in one of the results
A.Query.bulk_load([1, 2])
=> [%A{id: 1, bs: [%B{id: 1, children: []}]}, %A{id: 2, bs: []}] # note the second bs is empty
# expected result
A.Query.bulk_load([1, 2])
=> [%A{id: 1, bs: [%B{id: 1, children: []}]}, %A{id: 2, bs: [%B{id: 1, children: []]}]
I have some other models that I am preloading with the same framework that work perfectly, including preloading of nested associations. It seems to be the self-reference that jams things up. If I remove the preloading of :children, then the queries work as expected (except without the child data).
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixirconf-us
- #ai
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #hex
- #security









