2017-01-24 14 views
0

に私はこのエクトクエリを持っている:ビルダイナミック断片は、エクト

def sum(query) do 
    from aggregate in query, 
    select: %{ 
    ones: fragment("coalesce(sum(ones), 0)"), 
    twos: fragment("coalesce(sum(twos), 0)"), 
    threes: fragment("coalesce(sum(threes), 0)"), 
    fours: fragment("coalesce(sum(fours), 0)"), 
    fives: fragment("coalesce(sum(fives), 0)"), 
    unanswered: fragment("coalesce(sum(unanswered), 0)"), 
    n_size: fragment("coalesce(sum(n_size), 0)"), 
    comment_count: fragment("coalesce(sum(comment_count), 0)") 
    } 
end 

私はここで、各ライン上のfragment、​​3210とsumの重複が心配です。それを私自身の機能に移して、このように呼び出せる方法はありますか?

def sum(query) do 
    from aggregate in query, 
    select: %{ 
    ones: sum.("ones"), 
    twos: sum.("twos"), 
    ... 

答えて

4

これは、私の知る限り、プレーン機能を実行することはできませんが、あなたは、マクロでこれを行うことができます。

defmacro sum_or_zero(column) do 
    quote do 
    fragment(unquote("coalesce(sum(#{column}), 0)")) 
    end 
end 

など、それを呼び出す:

def sum(query) do 
    from aggregate in query, 
    select: %{ id: sum_or_zero("id") } 
end 

で上記の関数とマクロ、次のコード:

MyApp.User |> A.sum |> MyApp.Repo.one |> IO.inspect 

枚のプリント:

defmacro sum_or_zero(column) do 
    quote do 
     fragment("coalesce(sum(?), 0)", unquote(column)) 
    end 
    end 

    def sum(query) do 
    from aggregate in query, 
     select: %{ id: sum_or_zero(aggregate.id) } 
    end 

クエリは、クエリでテーブル名を使用します。この方法は:

[debug] QUERY OK source="users" db=1.9ms 
SELECT coalesce(sum(id), 0) FROM "users" AS u0 [] 
%{id: 6} 

でも、私は文字列の代わりにsum_or_zeroに列を渡すことをお勧め

[debug] QUERY OK source="users" db=1.9ms 
SELECT coalesce(sum(u0."id"), 0) FROM "users" AS u0 [] 
%{id: 6}