rbino

rbino

Ash Core Team

Correct way to filter with an inner join using Ash.Query

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?

Marked As Solved

zachdaniel

zachdaniel

Creator of Ash
Tag
|> Ash.Query.filter(exists(device_tags, true))
|> MyApi.read!(tenant: tenant)

Something like the above should do it :slight_smile:

Where Next?

Popular in Questions Top

WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New

Other popular topics Top

AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
johnnyicon
Hi all, I’ve just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage. I’m trying to use Postgres...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
Lily
In templates/appointment/index.html.eex: <%= for appointment <- @appointments do %> <tr> <td><%= appoi...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
grych
Hi folks, Few months ago I have announced the proof-of-concept of the library to manipulate the browsers DOM objects directly from Elixi...
639 52774 488
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New

We're in Beta

About us Mission Statement