gonzofish

gonzofish

Ecto: how to join three tables?

I’m currently trying to understand how to join three tables using Ecto. All the examples I’ve seen use 2, so maybe I’m just missing something.

  • I have 3 tables
    • users
    • teams
    • roles
  • The set of roles is a static set of 9 roles
  • A user belongs to many teams with a single role

If I was writing SQL by hand, I think the query would be something like:

SELECT *
FROM group_user_roles gur 
JOIN teams t
ON t.id = gur.team_id
JOIN roles r
ON r.id = gur.role_id
JOIN users u
ON u.id = gur.user_id

Or something like that…

Does anyone know how would I go about achieving something like this through Ecto?

Thanks for any responses/views!

Most Liked

kelvinst

kelvinst

The function you’re looking for is this: https://hexdocs.pm/ecto/Ecto.Query.html#join/5.

To write the same SQL you have would be something like:

Repo.all from gur in "group_user_roles", 
  join: t in "teams", on: t.id == gur.team_id,
  join: r in "roles", on: r.id == gur.role_id,
  join: u in "users", on: u.id == gur.user_id

That would have the same result of the select, and it does not use any Ecto.Schema. If you have the schemas like:

defmodule GroupUserRole do
  schema "group_user_roles" do
    belongs_to :user, User
    belongs_to :role, Role
    belongs_to :team, Team
  end
end

defmodule User do
  schema ...
end

defmodule Team do
  schema ...
end

defmodule Role do
  schema ...
end

You can do a simpler query:

Repo.all from gur in GroupUserRole, 
  join: t in assoc(:team),
  join: r in assoc(:role),
  join: u in assoc(:user)
13
Post #2
pystar

pystar

The quoted didn’t work for me (2021).
This did:

You can do a simpler query:

Repo.all from gur in GroupUserRole, 
  join: t in assoc(gur, :team),
  join: r in assoc(gur, :role),
  join: u in assoc(gur, :user)

Anyone know why? Syntax change? I am a newbie so pardon my question.

gonzofish

gonzofish

@kelvinst thanks for the reply! i’ll give that a shot

kelvinst

kelvinst

Sorry I took so long to answer. So basically it was not working for you because I typed my example straight in here and forgot to add the first argument of the assoc as you did. So that’s it, your version is actually the right one :smiley:

gdub01

gdub01

Yeah I guess it’s a little less convenient to access than just have user.team.role… but it’s more flexible. To be honest I forget where I was even using that code so I can’t quite remember how I liked accessing those fields.

GitHub - woylie/flop: Filtering, ordering and pagination for Ecto is an interesting library that enables queries on joins pretty easily. I’m not sure if that’d be relevant if you want to query things a little more conveniently.

Where Next?

Popular in Questions Top

srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
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
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
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
quazar
How to set Jason to encode all fields in ecto schema, I don’t care about security and implementing only is taking long list of attributes...
New
sacepums
Hey guys. I'm new to elixir and im really stocked about it. But I ran into a bit of problem - I need to convert a date sting, for examp...
New
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
Mooodi
Given a string, how can I get access to its character by index? Enum.at("my_string", 2) doesn't work. Or rather, not char, but a substr...
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

Other popular topics Top

Qqwy
Update: How to use the Blogs & Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3268 119930 1237
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 30048 115
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
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 49522 488
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 35421 110
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list....
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
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

We're in Beta

About us Mission Statement