如何构建动态的where子句?

How to build dynamic where clause?

我有字段名称列表,例如。 [:type, :car_id] 及其变更集 我想从每个字段中获取数据作为范围。 如何在从字段列表创建的每个表达式之间使用 and 构建动态 where 子句,我可以在之前创建的表达式中插入吗?

非动态示例:

def scoped_query(query, changeset, fields_names) do
  type_field = List.first(fields_names)
  car_id_field = List.last(fields_names)
  scope1 = get_field(changeset, type_field)
  scope2 = get_field(changeset, car_id_field)
  query |> where([m], field(m, ^type_field) == ^scope1 and field(m, ^car_id_field) == ^scope2)
end

您可以在初始查询中使用 Enum.reduce/3 来构建 wheres:

Enum.reduce([:type, :car_id], query, fn field, acc ->
  value = get_field(changeset, field)
  where(acc, [m],field(m, ^field) == ^value)
end)

由于您想在 == 上进行比较并将它们与 and 相结合,您可以简单地将关键字列表传递给 where,利用 Ecto 2.0 中的 Bindingless Queries +:

def scoped_query(query, changeset, fields_names) do
  criteria = for field <- fields_names, do: {field, get_field(changeset, field)}
  query |> where(^criteria)
end