Ecto 2.1 (there is a rc out) supports or_where
. So let’s assume you have your n conditions defined as follows:
conditions =
[{"admin", :boolean}, {"users_created", {:integer, 1}}, {"username", {:string, "jack"}}, ...]
What you need to do is to convert the data structure above into a query construct. Assuming you already have a query in the variable named query
, we can do that with reduce:
query =
Enum.reduce(conditions, query, fn
{field, :boolean}, query ->
query |> or_where([q], q.field == ^field and q.boolean_value)
{field, {:integer, integer}}, query ->
query |> or_where([q], q.field == ^field and q.integer_value > ^integer)
{field, {:string, string}}, query ->
query |> or_where([q], q.field == ^field and q.string_value == ^string)
... ->
...
end)
Depending on what you are building, you can clean up that code a bit but I am leaving it “dirty” for now and you can choose how to refactor it later.
With the query built, now you just need to group by and having:
query |> group_by([q], q.id) |> having([q], count(q.id) == ^length(conditions))
In case you really need count(*)
(I don’t think you do since you are grouping by id), you can use a fragment as others have said.