Hi there,
I’m currently working through the Craft GraphQL … book, which has been a nice journey through playing with both GraphQL and Ecto. I’ve followed the examples in the book but I’m actually applying them to a new project. So suppose I have a collection of Artists and each can have multiple Genres.
I’m building a query to filter a list of artists by genre. But as with any table that has a join you can end up with duplicate records. e,g,
SELECT a0."id", a0."name", a0."inserted_at", a0."updated_at" FROM "artists" AS a0 INNER JOIN "artists_genres" AS a2 ON a2."artist_id" = a0."id" INNER JOIN "genres" AS g1 ON a2."genre_id" = g1."id" WHERE (g1."name" ILIKE $1) ORDER BY a0."name" DESC ["%core%"]
Easy I’ll just throw in a DISTINCT and we’re good?
SELECT DISTINCT ON (a0."id") a0."id", a0."name", a0."inserted_at", a0."updated_at" FROM "artists" AS a0 INNER JOIN "artists_genres" AS a2 ON a2."artist_id" = a0."id" INNER JOIN "genres" AS g1 ON a2."genre_id" = g1."id" WHERE (g1."name" ILIKE $1) ORDER BY a0."id", a0."name" DESC ["%r%"]
Well seems not. The DISTINCT also has an ORDER BY a0.“id” added as well. I can’t work out why and if this is the default behaviours how can I then order my results by the name only.
def list_artists(args) do
# query = Shirts.Core.Artist
# query = from q in Shirts.Core.Artist, distinct: :id
query = Shirts.Core.Artist |> distinct([a], a.id)
args
|> Enum.reduce(query, fn
{_, nil}, query ->
query
{:order, order}, query ->
from q in query, order_by: {^order, :name}
{:matching, name}, query ->
from q in query, where: ilike(q.name, ^"%#{name}%")
{:filter, filter}, query ->
query |> filter_with(filter)
end)
|> Shirts.Repo.all
end
def filter_with(query, filter) do
Enum.reduce(filter, query, fn
{:name, name}, query ->
from q in query, where: ilike(q.name, ^"%#{name}")
{:genre, genre_name}, query ->
from q in query,
join: g in assoc(q, :genres),
where: ilike(g.name, ^"%#{genre_name}%")
end)
end
Any help would be greatly appreciated. Many thanks.
RobL