In my application I want to retrieve all tags that are currently assigned to at least a device.
In Ecto I did this with:
def list_device_tags do
query =
from t in Tag,
distinct: true,
join: dt in DeviceTag,
on: t.id == dt.tag_id
Repo.all(query)
end
What is the correct way to do the same thing with Ash.Query
?
Additional info
DeviceTag
is the join table between Device
and Tag
, and it has a composite primary key of tenant_id + device_id + tag_id
(I’m using attribute-based multitenancy).
In the Ash version I’ve also added a has_many :device_tags
relationship on the Tag
(which was needed before) to use it in filters.
What I tried
Tag
|> Ash.Query.filter(device_tags)
|> Ash.read!(tenant: tenant)
Results in:
** (Ash.Error.Unknown) Unknown Error
* filter: Invalid reference device_tags when hydrating relationship ref for [:device_tags]. Require single attribute primary key.
Tag
|> Ash.Query.filter(length(device_tags) > 1)
|> Ash.read!(tenant: tenant)
Results in the same error as above
Tag
|> Ash.Query.filter(device_tags.device_id)
|> Ash.read!(tenant: tenant)
Results in:
[debug] QUERY ERROR source="tags" db=0.0ms queue=17.2ms idle=1659.4ms
SELECT DISTINCT ON (t0."id") t0."id", t0."name", t0."inserted_at", t0."updated_at", t0."tenant_id" FROM "tags" AS t0 LEFT OUTER JOIN "public"."devices_tags" AS d1 ON t0."id" = d1."tag_id" WHERE (d1."device_id"::bigint) AND (t0."tenant_id"::bigint = $1::bigint) [1] module=Ecto.Adapters.SQL function=log/4
** (Ash.Error.Unknown) Unknown Error
* ** (Postgrex.Error) ERROR 42804 (datatype_mismatch) argument of AND must be type boolean, not type bigint
Tag
|> Ash.Query.filter(not is_nil(device_tags.device_id))
|> Ash.read!(tenant: 1)
Seems to do what I want, but the check on device_id
seems redundant.
Is this actually the way to go or am I missing something?