Horacio
Horacio

Reputation: 2965

how to write this where clause in Ecto

I have to filter an index that could accept in some cases comma separated values. Im working with Ecto, without phoenix (with cowboy).

my index will support some search like this

/users?ids=1,2,3&[email protected]&another=something

where email field doesn't allow more than one parameter and ids supports more than 1 id

This is what I've tried

def list_all(query_params) do
    filtered_params = prepare_list_query(query_params)

    User
    |> where(^filtered_params)
    |> Repo.all()
  end

  # In order to simplify queries I decided to manage all queries as IN clause
  # it will returns [id: [1,2,3], email:["[email protected]"]]

  defp prepare_list_query(query_params) do
    query_params
    |> Map.take(~w(ids email another))
    # Careful: read reference #1 above
    |> Enum.map(fn {name, value} ->
      case name do
        "ids" -> {:id, String.split(value, ",")}
        single_param -> {String.to_atom(single_param), [value]}
      end
    end)
  end

It's tricky but my idea is to return

[id: [1,2,3], email:["[email protected]"]]

and then working all filters as IN clause.

This filter has to support to send zero, one or all parameters.

I'm brand new in elixir world and I’m doing my first steps.

Thanks in advance :).

Upvotes: 0

Views: 496

Answers (1)

Badu
Badu

Reputation: 1082

You can use Enum.reduce/3 to dynamically build an ecto query based on the params

def list_all(query_params) do
    query = User # initial query

    query_params
    |> Map.take(~w(ids email another))
    |> Enum.reduce(query, fn 
      {_key, value} when value in [nil, ""], q ->
          q # ignore empty values          
      {"ids", value}, q -> 
          ids = String.split(values, ",")
          q |> where([r], r.id in ^ids) 
      {key, value} ->
          args = [{key, value}] 
          q |> where(^args)
      end
    end)
    |> Repo.all()
  end

In the reduce function you can add new clauses to handle different keys and values.

Upvotes: 2

Related Questions