如何在Ecto中编写此where子句

时间:2019-06-15 15:43:48

标签: elixir ecto phoenix

我必须过滤一个在某些情况下可以接受逗号分隔值的索引。我在Ecto工作,没有凤凰(和牛仔一起)。

我的索引将支持这样的搜索

/users?ids=1,2,3&email=simple@email.com&another=something

其中电子邮件字段不允许使用多个参数,并且ID支持多个ID

这是我尝试过的

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:["something@mymail.com"]]

  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

这很棘手,但我的想法是回来

[id: [1,2,3], email:["something@mymail.com"]]

,然后将所有过滤器用作IN子句。

此过滤器必须支持发送零个,一个或所有参数。

我是长生不老药世界中的新人,我正在迈出第一步。

预先感谢:)。

1 个答案:

答案 0 :(得分:2)

您可以使用Enum.reduce/3根据参数动态构建ecto查询

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

在reduce函数中,您可以添加新子句来处理不同的键和值。