2016-06-11 15 views
0

Ich bin neu in Elixir und Phoenix Framework. Wie kann ich Parameter dynamisch zur ecto Abfrage hinzufügen? Zum Beispiel:Ecto dynamische Abfrageparameter in Phoenix Framework

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

Ist es möglich, _params in Ecto Abfrage zu verwenden? Etwas wie:

Repo.get_by(Department, _params) 

Antwort

3

Sie können dafür "bindingless queries" verwenden, aber es gibt ein Problem. Ecto erwartet die Spaltennamen als Atome und das Argument als Keyword-Liste. Letzteres ist einfach, aber converting arbitrary user input into atoms may result in the Erlang VM crashing. Hier ist ein sicherer Weg, dies mit einer weißen Liste von Spaltennamen zu tun:

# 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 

Ausgang:

[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

Sie Sachen dynamisch ofcourse bekommen können, Repo.get_by im zweiten Argument erwartet Keyword.t | Map.t, entweder ein Schlüsselwort oder eine Karte. Sie können es direkt von Params in eine Map oder ein Schlüsselwort setzen und diese an die Abfrage übergeben. Beispiel

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 

Wie @Dogbert in den Kommentaren angegeben, dass get_by werden Sie 0 oder 1 Ergebnis erhalten, werden weitere Ergebnisse einen Fehler erhöhen. Ich habe es nur benutzt, weil du get_by in der Frage benutzt hast.

+1

Beachten Sie, dass 'Repo.get_by' nur 0 oder 1 Ergebnis verwendet wird, holen (s). Wenn die Abfrage mehr als 1 Ergebnisse zurückgibt, wird ein Fehler ausgelöst. – Dogbert

Verwandte Themen