Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elixir Ecto : multiple joins and reusable/composable queries

In Ecto you can make reusable/composable queries like so :

defmodule AModel
  #...
    
  def anonymous(q), do: q |> where([am], is_null(am.user_id))
  end
end

See more examples on this blog post.

However, I face a problem using multiple joins.

Let's suppose we have a schema that looks like this :

  • AModel belongs to BModel
  • BModel belongs to CModel
  • CModel belongs to DModel

The solution proposed in this article does not really work with deep joins :

q = DModel
  |> join(:inner, [dm], cm in assoc(dm, :c_models))
  |> join(:inner, [_, cm], bm in assoc(cm, :b_models))
  |> join(:inner, [_, _, bm], am in assoc(bm, :a_models)) 
  |> AModel.anonymous

Querying functions take as first (second for join) argument a binding table. It contains the previous joins and is sadly tight to join order.

In our case, the anonymous function target the starting table. However in the query example, AModel is the 4th binding ...

Any idea or technic to get rid of this order dependency ?

EDIT :

I get an answer from the blog author. He told me that there is no native other way to handle bindings than by position in the table. He also gave this article highlighting this fact.

But for god sake, if order only matter, why I can't create above it a naming mapping that associates name with binding index ?

Is this too much to ask :p ?

like image 974
ProxyGear Avatar asked Oct 16 '15 12:10

ProxyGear


1 Answers

Use named bindings

Ecto 3.0 added named bindings for this use case.

like image 71
Nathan Long Avatar answered Nov 09 '22 02:11

Nathan Long