将 Ecto 片段提取到变量中

Extracting Ecto fragment into variable

我有一个片段,它是重复的并且相当复杂。我想将它提取到 variable/function 中并多次重复使用它,而不是多次编写它。这是我迄今为止尝试过的许多不同方法中的一个简化示例:

f = dynamic([u], fragment("order by name desc"))
query = from(u in User)
        |> order_by([u], ^f)
Repo.all(query)

根据documentation,使用dynamic应该是可能的,但是我在order_byselecthaving或任何我得到的范围内尝试类似于以下内容的错误消息:

(ArgumentError) expected a field as an atom, a list or keyword list in `order_by`, got: `dynamic([u], fragment("order by name desc"))`

我将如何实现它?


更新 1

这里有更多真实的例子。以下代码有效:

    from(p in Photo,
      join: pv in assoc(p, :v),
      left_join: pl in assoc(p, :l),
      left_join: pc in assoc(p, :c),
      select: %{p | last_activity_at: fragment("greatest(?, ?, ?)", max(p.inserted_at), max(pl.inserted_at), max(pc.inserted_at))},
      group_by: p.id,
      order_by: [desc: fragment("greatest(?, ?, ?)", max(p.inserted_at), max(pl.inserted_at), max(pc.inserted_at))]
    )

但是,我无法通过提取片段或将其与动态或其他方式一起使用来使其工作。

Ecto.Query.dynamic/2

的同一文档中有一个 order_by 的示例
f = dynamic([u], fragment("order by name desc"))
# order_by = [desc: :name] # why not just this?
order_by = [desc: ^f]
query = from(u in User), order_by: ^order_by
Repo.all(query)

对于更新的示例:

order = dynamic(
  [p, pl, pc], 
  fragment(
    "greatest(?, ?, ?)",
    max(p.inserted_at),
    max(pl.inserted_at),
    max(pc.inserted_at)
  )
)

from(
  p in Photo,
  join: pv in assoc(p, :v),
  left_join: pl in assoc(p, :l),
  left_join: pc in assoc(p, :c),
  select: ...,
  group_by: p.id,
  order_by: ^[desc: order]
)

如文档中所述,

it is not possible to pass dynamics outside of a root. For example, this won't work:

 from query, order_by: [asc: ^dynamic(...)]

But this will:

from query, order_by: ^[asc: dynamic(...)]