@peerreynders yes I guess I fell into the trap of asking of a way to implement the solution I had in my mind than describing the actual problem
I more or less want to create a dynamic query filtering mechanism. For example, I’ve got the following query:
whs_query =
from(w in Withholding,
join: b in Beneficiary,
on: [id: w.beneficiary_id],
join: a in Authority,
on: [id: w.authority_id],
join: ak in AuthorityKind,
on: [id: a.authority_kind_id],
preload: [beneficiary: b, authority: {a, authority_kind: ak}],
order_by: [asc: w.pay_date, asc: w.id]
)
and I want to filter on various fields from all relations (w, b, a, ak)
.
Now in non-dynamic case, I’ll create a schemaless changeset using something like
types = %{
status: :string,
afm: :string,
# year: :integer,
authority: :string,
authority_kind: :string
}
{%{}, types}
|> Ecto.Changeset.cast(params, Map.keys(types))
and finally retrieve the changes from the changeset and filter on the initial query:
changes = Map.fetch!(changeset, :changes) |> IO.inspect()
whs_query =
case changes[:status] do
nil -> whs_query
v -> whs_query |> where([w], w.status == ^v)
end
whs_query =
case changes[:afm] do
nil -> whs_query
v -> whs_query |> where([w, b], b.afm == ^v)
end
# etc
This works fine however it is a lot of work to do all this again and again for all my filters.
So instead I thought of modeling the filters I’d need for each query using a simple structure like:
filters= [
%{name: :status, type: :string, pos: 0},
%{name: :afm, type: :string, pos: 1}
]
– please notice that the pos
defines the position in the named query i.e status
is for Withholding
(pos 0) while afm
is for Beneficiary
(pos 1) –
and then do something like:
changeset = QueryFilterEx.make_filter_changeset(filters, filter_params)
whs_query =
from(w in whs_query,
join: b in Beneficiary,
on: [id: w.beneficiary_id],
join: a in Authority,
on: [id: w.authority_id],
join: ak in AuthorityKind,
on: [id: a.authority_kind_id],
preload: [beneficiary: b, authority: {a, authority_kind: ak}],
order_by: [asc: w.pay_date, asc: w.id]
) |> QueryFilterEx.filter(filters, changeset)
So now the problem is that I have the initial query which is passed to QueryFilterEx.filter
and I want to dynamically filter it using the filters
struct I defined before to add where clauses to it. This leads me to the problem I described in my 1st and 2nd post
Also, concerning named bindings i really don’t think that it would solve my problem because I still wouldn’t be able to dynamically construct the aliases of the bindings in the where clauses.
BR,
Serafeim