【问题标题】:Building Dynamic fragments in Ecto在 Ecto 中构建动态片段
【发布时间】:2017-01-24 13:08:37
【问题描述】:

我有这个 Ecto 查询:

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

我担心这里每一行的fragmentcoalescesum 重复。有没有办法可以将它移到它自己的函数中并像这样调用它?

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

【问题讨论】:

    标签: elixir ecto


    【解决方案1】:

    据我所知,这不能用普通函数来完成,但你可以用宏来做到这一点:

    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
    

    打印:

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

    我建议将列传递到 sum_or_zero 而不是字符串:

      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(u0."id"), 0) FROM "users" AS u0 []
    %{id: 6}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-04
      • 1970-01-01
      • 2020-12-27
      • 2016-09-06
      • 2017-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多