Hey Folks!
I’m building out an Ecto query and have run into a block.
I need to get all Evenings that contain certain Event types.
I’m trying to find evenings that have events with type1 AND 2
Here’s my schema:
schema "evenings" do
has_many :events, Event
...
end
schema "events" do
type, :integer
belongs_to :evening, Evening, type: :binary_id
...
end
When I query like so I get Evenings with type1 or 2:
types = [1,2]
from ev in Evening,
join: e in assoc(ev, :events),
preload: [events: e],
where: e.type in ^types
Even more, you’ll get duplicated Evenings when multiple events are found.
As I understand, you need Evenings which have more than 1 event with type 1 and more than 1 event with type 2. Is it correct?
types = [1, 2]
evening_id_with_event_types_query =
from events in Event,
group_by: events.evening_id,
select: %{types: fragment("ARRAY_AGG(DISTINCT(?))", events.type), evening_id: events.evening_id}
from evenings in Evening,
inner_join: evening_id_with_event_types in subquery(evening_id_with_event_types_query),
on: evening_id_with_event_types.evening_id == evenings.id,
where: evening_id_with_event_types.types == ^types
AFAIK distinct automatically applies ordering, so evening_id_with_event_types.types is sorted alphabetically and types should be sorted too.
Thanks for the answer! I wasn’t clear about it so I had to do a little more digging to get the expected behavior. I wanted to get Evenings with at least the event types listed; IE if I ask for Event types [1, 2], it’s okay if the Evening has Events with types [1, 2, 3]
event_query = from event in Event,
group_by: event.evening_id,
select: %{types: fragment("ARRAY_AGG(DISTINCT(?))", event.type), evening_id: event.evening_id}
from evening in query,
inner_join: event in subquery(event_query),
on: event.evening_id == evening.id,
where: fragment("? @> ?", event.types, ^types)