2016-06-11 1 views
0

필자는 Elixir 및 Phoenix 프레임 워크를 처음 사용합니다. ecto 쿼리에 매개 변수를 동적으로 추가하려면 어떻게해야합니까? 예 :phoenixframework의 Ecto 동적 쿼리 매개 변수

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

Ecto 쿼리에서 _params를 사용할 수 있습니까? 같은 : 두 번째 인수의 동적 당연히 물건을 얻을 수

Repo.get_by(Department, _params) 

답변

3

"bindingless queries"을 사용할 수 있지만 문제가 있습니다. Ecto는 열 이름이 원자이고 인수가 키워드 목록 이길 기대합니다. 후자는 쉽지만, converting arbitrary user input into atoms may result in the Erlang VM crashing입니다. 여기에 열 이름의 화이트리스트를 사용하여이 작업을 수행 할 수있는 안전한 방법입니다 :

# 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 

출력 : Repo.get_by` 만 0 또는 1 결과 (들)을 가져 오는 데 사용되는 '것을

[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

, Repo.get_by는 키워드 또는지도 중 하나를 Keyword.t | Map.t을 기대하고있다. params에서 Map 또는 키워드로 직접 설정할 수 있으며이를 쿼리에 전달할 수 있습니다. @Dogbert가 get_by는 0 또는 1 결과를 얻을 것이라는 의견에 명시된 바와 같이 예

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 

, 더 많은 결과에서 오류가 발생합니다. 질문에 get_by을 사용했기 때문에 나는 그것을 사용했습니다.

+1

참고. 쿼리가 두 개 이상의 결과를 반환하면 오류가 발생합니다. – Dogbert