where
is a macro that accepts a query as the first argument and returns a query so it can be used in pipelines. Piping many where
s results in combining them with AND
. If you want to combine the where clauses with OR
, you can use the or_where
macro.
So, the following code:
query
|> where([user], user.id == ^user.id)
|> where([user], user.name == ^user.name)
will generate an SQL query that looks something like this:
WHERE user.id = 1 AND user.name = 'somename'
The second argument is a list of the so called bindings
. In the example above, the user
is a binding. Bindings work a lot like table aliases in SQL and effectively gives you a variable for referring to your table throughout your query (This description is taken from the great Programming Ecto which gives deep insight on how Ecto works and how to use it). The bindings list can contain more than one element in case the query contains joins. When using joins, the bindings should be matched in the order they are specified.
from(user in User)
|> join(:inner, [user], user_settings in assoc(u, :user_settings))
|> where([_user, us], where: us.role == "admin")
The bindings variable names can differ but they point to the same thing. In the example above, the user settings in join
are bound to the user_settings
variable, but in the where
clause they are bound to the us
variable.
Named bindings are also possible and they can solve some problems that the non-named bindings cannot, but they are not being described here. More for them can be found in the Ecto Documentation.
The last argument in the where
macro is an expression that must evaluate to a boolean value. This expression contains the actual where clauses you want to write.