If you have a virtual field, say field(:users, {:array, :map}, virtual: true}
what is the best way to populate that field with multiple records when querying the record? For example:
defmodule App.Topic do
schema "topics" do
field(:name, :string)
field(:description, :string)
field(:users, {:array, :map}, virtual: true)
end
end
defmodule App.VirtualUser do
embedded_schema do
field(:name, :string)
field(:id, :string)
end
end
In this case there is a bit of info from the user that is required by the topic but it may not make sense to load a full User
struct for various reasons.
When querying a Topic I’d write something like this:
Topic
|> from(as: :topic)
|> join(:left, [topic: t], u in assoc(t, :users), as: :user)
|> join(:left, [user: u], p in. assoc(p, :profile), as: :profile)
|> select_merge([topic: t, user: u, profile: p],
%{users: %VirtualUser{name: p.name, id: u.id}
)
Perhaps you can see the issue, this works when there is a single user, but when multiple users are associated with a Topic
it breaks because select_merge/2
(I think), throws an error: ** (Ecto.MultipleResultsError) expected at most one result but got 2 in query
which fair enough.
I’m by no means a Postgres guru or SQL in general for that matter, so what I’m attempting may not be possible but if theres a way of loading/associating multiple records on the record I’m very interested.
Further info: in this case preloads aren’t an option because my ultimate goal is to combine a few different types of records into the VirtualUser
struct. The idea being that VirtualUser
can be a uniform shape that I can load different records into (for example a User
struct and a Guest
struct could look very different from each other but each be merged into a VirtualUser
struct.