How do interpolation fields in Ecto queries?

不问归期 提交于 2021-02-08 11:14:52

问题


The Ecto documentation shows how to do interpolation values. But I need dynamic fields in my queries. I have dozens of fields and write queries for each of them does not seem cohesive.

defmodule Hedone.SearchController do
  use Hedone.Web, :controller

  alias Hedone.User

  def idade(conn, %{"idade+" => maior, "idade-" => menor, "campo" => campo}) do
    IO.inspect campo
  query = from u in User, where: u.campo > ^maior and u.campo < ^menor, select: u.name
  pesquisa = Repo.all query
  IO.inspect pesquisa
  text conn, "Works"
end

end

This controller generates the following error:

** (Ecto.QueryError) web/controllers/search.ex:8: field `Hedone.User.campo` in `where` does not exist in the schema in query:

from u in Hedone.User,
  where: u.campo > ^18 and u.campo < ^40,
  select: u.name

Automatically translated.


回答1:


I'm assuming campo contains a string with the name of the field you want to use, e.g. "age". You can use field in the query for this:

def idade(conn, %{"idade+" => maior, "idade-" => menor, "campo" => campo}) do
  campo = String.to_existing_atom(campo)
  query = from u in User, where: field(u, ^campo) > ^maior and field(u, ^campo) < ^menor, select: u.name
  pesquisa = Repo.all query
  IO.inspect pesquisa
  text conn, "Works"
end

field expects the field to be an atom, so I've used String.to_existing_atom to safely convert a string to atom. Since you already must have defined the field in the schema of the model, String.to_existing_atom will not fail for any valid field name.




回答2:


I am posting this as an example of another approach to the problem. One might use macros to handle this transformation since macros are being resolved in compile time:

defmacro idade(conn, formula, campo: binding) do
  q = formula |> String.replace "campo", binding
  quote do
    from u in User, where: unquote(q), select: u.name
      |> Repo.all
    text conn, "Works"
  end
end

and call it like:

idade(nil, "u.campo > ^maior and u.campo < ^menor", campo: "age")


来源:https://stackoverflow.com/questions/39687581/how-do-interpolation-fields-in-ecto-queries

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!