如何通过 ecto 将从 STR 返回的集合检索到模型中?

How can I retrieve the set returned from a STR into a model via ecto?

我在 postgreSQL 上有一组返回函数,例如

CREATE FUNCTION set_ret_func(foo int, bar int) 
  RETURNS TABLE(total bigint, result bigint) AS $$
    SELECT a.val +  as total, b.val +  as result 
    FROM a, b
  $$ LANGUAGE SQL;

此函数为我提供了一个 "flexible view",我可以轻松调用它:

SELECT * from set_ret_func('30'::int, '89'::int)

环顾四周,我发现可以通过 Ecto.Repo 执行类似

的操作来调用多态关联
from( x in {"table_name", Model}, select: x.total )
|> Repo.all

这让我想知道我是否可以使用 Ecto.Query 或 Ecto.Query 中的 fragment/1。from/2 中的 API 所以我能够将我的集合返回函数调用到架构中(它们都将在 column_name 上匹配),根据我的想象,它看起来像这样:

from( srf in {fragment("set_ret_func(?::int, ?::int)", var1, var2), Model},
   select: srf.total)

是否有调用此 STR 并将其转换为模型的实际方法?

老实说,最简单的方法是 Ecto.Adapters.SQL.query。您仍然可以将其加载到模型中。这是一个应该大致正确的快速片段:

with {:ok, %{columns: cols, rows: rows}} <- Ecto.Adapters.SQL.query(Repo, "SELECT * FROM set_rec_func(?,?)", [var1, var2])
   fields = Enum.map(cols, &String.to_existing_atom/1) do
   for row <- rows, values = Enum.zip(fields, rows) do
     struct(Model, values) |> Ecto.put_meta(state: :loaded)
   end
end

尽管这并不是您的 ecto 查询试图做的,select 只是一个字段而不是整个模型。实际上,在 Ecto 中并没有那么多的模型魔术。所有真正的魔法都发生在 Ecto.Query API 和 Ecto.Changeset API 中。事实上,为了防止将来出现混淆,Ecto 2.0(几天之内)将完全删除 "Model" 这个词。它们都是与某些模式元数据相关联的普通结构。