phoenixframework中

时间:2016-06-11 15:43:39

标签: elixir phoenix-framework ecto

我是Elixir和Phoenix框架的新手。如何动态添加参数到ecto查询?例如:

def index(conn, _params) do
  departments = Repo.all(Department)
  render(conn, "index.json", data: departments)
end

是否可以在Ecto查询中使用_params?类似的东西:

Repo.get_by(Department, _params)

2 个答案:

答案 0 :(得分:3)

您可以使用converting arbitrary user input into atoms may result in the Erlang VM crashing来解决此问题,但这有问题。 Ecto期望列名为atoms,参数为关键字列表。后者很简单,但是{{3}}。以下是使用列名称白名单执行此操作的安全方法:

# user input
params = %{"first_name" => "John", "last_name" => "Smith", "age" => 28}
filtered_params =
  params
  |> Map.take(~w(first_name last_name age))
  |> Enum.map(fn {k, v} -> {String.to_atom(k), v} end)

from(MyApp.Person, where: ^filtered_params)
|> MyApp.Repo.all
|> IO.inspect

输出:

[debug] SELECT p0."id", p0."first_name", p0."last_name", p0."age", p0."inserted_at", p0."updated_at" FROM "people" AS p0 WHERE (((p0."age" = ?) AND (p0."first_name" = ?)) AND (p0."last_name" = ?)) [28, "John", "Smith"] OK query=6.5ms queue=14.8ms
[%MyApp.Person{__meta__: #Ecto.Schema.Metadata<:loaded>, age: 28,
  first_name: "John", id: 1, inserted_at: #Ecto.DateTime<2016-06-11T16:01:49Z>,
  last_name: "Smith", updated_at: #Ecto.DateTime<2016-06-11T16:01:49Z>}]

答案 1 :(得分:1)

你可以动态地获取资源,第二个参数中的Repo.get_by期望Keyword.t | Map.t,无论是关键字还是地图。您可以将它直接从params设置为Map或关键字,并将其传递给查询。 实施例

def index(conn, _params) do
  query_conditions = [id: params["id"], name: params["department_name"] ]
  departments = Repo.get_by(Department, query_conditions)
  render(conn, "index.json", data: departments)
end

正如@Dogbert在评论中所说get_by会得到0或1结果,更多结果会引发错误。我只使用它,因为你在问题中使用了get_by