Ecto.Query.dynamic
dynamic
, go back to Ecto.Query module for more information.
Builds a dynamic query expression.
Dynamic query expressions allow developers to compose query expressions bit by bit, so that they can be interpolated into parts of a query or another dynamic expression later on.
Examples
Imagine you have a set of conditions you want to build your query on:
conditions = false
conditions =
if params["is_public"] do
dynamic([p], p.is_public or ^conditions)
else
conditions
end
conditions =
if params["allow_reviewers"] do
dynamic([p, a], a.reviewer == true or ^conditions)
else
conditions
end
from query, where: ^conditions
In the example above, we were able to build the query expressions bit by bit, using different bindings, and later interpolate it all at once into the actual query.
A dynamic expression can always be interpolated inside another dynamic expression and into the constructs described below.
where
, having
and a join
's `on'
The dynamic
macro can be interpolated at the root of a where
,
having
or a join
's on
.
For example, assuming the conditions
variable defined in the
previous section, the following is forbidden because it is not
at the root of a where
:
from q in query, where: q.some_condition and ^conditions
Fortunately that's easily solved by simply rewriting it to:
conditions = dynamic([q], q.some_condition and ^conditions)
from query, where: ^conditions
order_by
Dynamics can be interpolated inside keyword lists at the root of
order_by
. For example, you can write:
order_by = [
asc: :some_field,
desc: dynamic([p], fragment("?>>?", p.another_field, "json_key"))
]
from query, order_by: ^order_by
Dynamics are also supported in order_by/2
clauses inside windows/2
.
As with where
and friends, it is not possible to pass dynamics
outside of a root. For example, this won't work:
from query, order_by: [asc: ^dynamic(...)]
But this will:
from query, order_by: ^[asc: dynamic(...)]
group_by
Dynamics can be interpolated inside keyword lists at the root of
group_by
. For example, you can write:
group_by = [
:some_field,
dynamic([p], fragment("?>>?", p.another_field, "json_key"))
]
from query, group_by: ^group_by
Dynamics are also supported in partition_by/2
clauses inside windows/2
.
As with where
and friends, it is not possible to pass dynamics
outside of a root. For example, this won't work:
from query, group_by: [:some_field, ^dynamic(...)]
But this will:
from query, group_by: ^[:some_field, dynamic(...)]
Updates
A dynamic
is also supported inside updates, for example:
updates = [
set: [average: dynamic([p], p.sum / p.count)]
]
from query, update: ^updates