Ecto.Query.select_merge
select_merge
, go back to Ecto.Query module for more information.
Mergeable select query expression.
This macro is similar to select/3
except it may be specified
multiple times as long as every entry is a map. This is useful
for merging and composing selects. For example:
query = from p in Post, select: %{}
query =
if include_title? do
from p in query, select_merge: %{title: p.title}
else
query
end
query =
if include_visits? do
from p in query, select_merge: %{visits: p.visits}
else
query
end
In the example above, the query is built little by little by merging into a final map. If both conditions above are true, the final query would be equivalent to:
from p in Post, select: %{title: p.title, visits: p.visits}
If :select_merge
is called and there is no value selected previously,
it will default to the source, p
in the example above.
The argument given to :select_merge
must always be a map. The value
being merged on must be a struct or a map. If it is a struct, the fields
merged later on must be part of the struct, otherwise an error is raised.
If the argument to :select_merge
is a constructed struct
(Ecto.Query.API.struct/2
) or map (Ecto.Query.API.map/2
) where the source
to struct or map may be a nil
value (as in an outer join), the source will
be returned unmodified.
query =
Post
|> join(:left, [p], t in Post.Translation,
on: t.post_id == p.id and t.locale == ^"en"
)
|> select_merge([_p, t], map(t, ^~w(title summary)a))
If there is no English translation for the post, the untranslated post
title
will be returned and summary
will be nil
. If there is, both
title
and summary
will be the value from Post.Translation
.
select_merge
cannot be used to set fields in associations, as
associations are always loaded later, overriding any previous value.