Is it possible to compose a query that returns all of a model (i.e. Post) with an aggregate count of one of it's associations (i.e. Like).
Repo.all(from p in Post,
join: l in Like,
where l.post_id == p.id,
group_by: p.id,
select: {p, count(l.id)
I've tried using group_by and select (above), but this only partially works. The results from the query exclude all of posts that don't have any likes.
If this is not possible, what's the best way to handle this problem? First thing that comes to mind mapping over the results of the query like such:
posts =
Repo.all Post
|> Enum.map(fn(post) ->
likes_query = from l in Like, where: l.post_id == ^post.id
likes_count = Repo.aggregate(likes_query, :count, :id)
%{post: post, likes_count: likes_count}
end)
There are two things wrong with the query:
You need to use on
instead of where
to specify the join condition
You need to use left_join
instead of join
if you want posts with no likes to be returned.
Final query:
from p in Post,
left_join: l in Like,
on: l.post_id == p.id,
group_by: p.id,
select: {p, count(l.id)}
You can also use assoc
in left_join
here which will add the correct on
automatically:
from p in Post,
left_join: l in assoc(p, :likes),
group_by: p.id,
select: {p, count(l.id)}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With