Here is an example trying to aggregate on a different field. This query returns only 9 records with more than 4 interactions, which agrees with the sql:
iex(50)> FiveWhys.Understand.Session |> Ash.Query.filter(count(interactions) > 4) |> Ash.read!(authorize?: false) |> length
[debug] QUERY OK source="sessions" db=37.6ms idle=511.7ms
SELECT s0."id", s0."title", s0."shared", s0."updated_at", s0."inserted_at", s0."user_id", s0."problem_statement", s0."prior_session_id" FROM "sessions" AS s0 LEFT OUTER JOIN LATERAL (SELECT si0."session_id" AS "session_id", coalesce(count(*), $1::bigint)::bigint AS "aggregate_0" FROM "public"."interactions" AS si0 WHERE (s0."id" = si0."session_id") GROUP BY si0."session_id") AS s1 ON TRUE LEFT OUTER JOIN "public"."summaries" AS s2 ON s0."id" = s2."session_id" LEFT OUTER JOIN LATERAL (SELECT si0."session_id" AS "session_id", any_value(si0."inserted_at"::timestamp ORDER BY si0."inserted_at" DESC ) FILTER (WHERE si0."inserted_at"::timestamp IS NOT NULL)::timestamp AS "latest_interaction_date" FROM "public"."interactions" AS si0 WHERE (s0."id" = si0."session_id") GROUP BY si0."session_id") AS s3 ON TRUE WHERE (coalesce(s1."aggregate_0", $2::bigint)::bigint::bigint > $3::bigint::bigint) ORDER BY (CASE WHEN NOT (s2."id"::uuid IS NULL) AND (s2."inserted_at"::timestamp::timestamp > s3."latest_interaction_date"::timestamp::timestamp) THEN s2."inserted_at"::timestamp ELSE s3."latest_interaction_date"::timestamp END)::timestamp DESC [0, 0, 4]
↳ anonymous fn/3 in AshPostgres.DataLayer.run_query/2, at: lib/data_layer.ex:785
9
select count(*) from (select s.id, count(*) from sessions s inner join interactions i on s.id = i.session_id group by s.id having count(*) > 4
);
count
-------
9
(1 row)
This query returns 15 (all of the sessions):
iex(51)> FiveWhys.Understand.Session |> Ash.Query.aggregate(:count_of_interactions, :count, :interactions) |> Ash.Query.filter(:count_of_interactions > 4) |> Ash.read!(authorize?: false) |> length
[debug] QUERY OK source="sessions" db=19.7ms queue=1.0ms idle=868.8ms
SELECT s0."id", s0."title", s0."shared", s0."updated_at", s0."inserted_at", s0."user_id", s0."problem_statement", s0."prior_session_id", coalesce(s1."count_of_interactions"::bigint, $1::bigint)::bigint FROM "sessions" AS s0 LEFT OUTER JOIN LATERAL (SELECT si0."session_id" AS "session_id", coalesce(count(*), $2::bigint)::bigint AS "count_of_interactions" FROM "public"."interactions" AS si0 WHERE (s0."id" = si0."session_id") GROUP BY si0."session_id") AS s1 ON TRUE LEFT OUTER JOIN "public"."summaries" AS s2 ON s0."id" = s2."session_id" LEFT OUTER JOIN LATERAL (SELECT si0."session_id" AS "session_id", any_value(si0."inserted_at"::timestamp ORDER BY si0."inserted_at" DESC ) FILTER (WHERE si0."inserted_at"::timestamp IS NOT NULL)::timestamp AS "latest_interaction_date" FROM "public"."interactions" AS si0 WHERE (s0."id" = si0."session_id") GROUP BY si0."session_id") AS s3 ON TRUE ORDER BY (CASE WHEN NOT (s2."id"::uuid IS NULL) AND (s2."inserted_at"::timestamp::timestamp > s3."latest_interaction_date"::timestamp::timestamp) THEN s2."inserted_at"::timestamp ELSE s3."latest_interaction_date"::timestamp END)::timestamp DESC [0, 0]
↳ anonymous fn/3 in AshPostgres.DataLayer.run_query/2, at: lib/data_layer.ex:785
15
select count(*) from sessions;
count
-------
15
(1 row)