2016-09-25 25 views
0

Ecto documentation顯示如何執行插值。但我在查詢中需要動態字段。我有幾十個領域,併爲他們每個人寫查詢似乎不具有凝聚力。Ecto查詢中的插值字段如何?

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 

該控制器生成以下錯誤:

** (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 

自動翻譯。

回答

2

我假設campo包含您要使用的領域,例如名稱的字符串"age"。您可以在查詢中使用field此:

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預計該領域是一個原子,所以我用String.to_existing_atom將字符串安全轉換爲原子。由於您已經必須在模型的架構中定義該字段,所以對於任何有效的字段名稱,String.to_existing_atom都不會失敗。

+0

對於動態fields_的_dozens我寧願用宏去。 – mudasobwa

+0

對不起,我開始編程,並期待將我的想法在線。我沒有閱讀宏會話。爲什麼會更好?所以它工作得很好。 –

+0

@mudasobwa你如何在這裏使用宏?你能擴展一下嗎?我想不出有什麼理由要這樣做,但也許我錯過了一些東西。 – Dogbert

1

我發佈這個作爲問題的另一種方法的示例。有人可能會使用宏來處理這種轉變,因爲宏在編譯時得到解決:

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 

,並調用它像:

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