当前位置: 首页 > 知识库问答 >
问题:

如何将原始sql与ecto Repo一起使用

司马奇希
2023-03-14

我有一个upsert需求,所以我需要调用postgres存储过程或使用公共表表达式。我还将pgcrypto扩展用于密码,并希望使用postgres函数(例如“crypt”来编码/解码密码)。

但是我找不到让ecto部分或全部使用原始sql的方法,是不是打算让ecto只支持长生不老的dsl,而不允许在dsl不够用的情况下使用原始sql?

我发现我可以通过适配器进行查询(Rocket是应用程序的名称)

q = Ecto.Adapters.Postgres.query(Rocket.Repo,"select * from users limit 1",[])

但不确定如何将其带到模型中。我是长生不老药的新手,似乎我应该能够使用 Ecto.Model.Schem.schema/3,但这失败了

Rocket.User.__schema__(:load,q.rows |> List.first,0)
** (FunctionClauseError) no function clause matching in Rocket.User.__schema__/3    

共有3个答案

宣高朗
2023-03-14

现在 Ecto 1.0 已经出来了,这应该可以工作一段时间:

将以下函数添加到Repo模块中:

def execute_and_load(sql, params, model) do
  Ecto.Adapters.SQL.query!(__MODULE__, sql, params)
  |> load_into(model)
end

defp load_into(response, model) do
  Enum.map response.rows, fn(row) ->
    fields = Enum.reduce(Enum.zip(response.columns, row), %{}, fn({key, value}, map) ->
      Map.put(map, key, value)
    end)

    Ecto.Schema.__load__(model, nil, nil, [], fields, &__MODULE__.__adapter__.load/2)
  end
end

并照此使用:

Repo.execute_and_load("SELECT * FROM users WHERE id = $1", [1], User)
巴洲
2023-03-14

ECTO 2.0的修改解决方案:

在repo.ex中:

  def execute_and_load(sql, params, model) do
    Ecto.Adapters.SQL.query!(__MODULE__, sql, params)
    |> load_into(model)
  end

  defp load_into(response, model) do
    Enum.map(response.rows, fn row ->
      fields = Enum.reduce(Enum.zip(response.columns, row), %{}, fn({key, value}, map) ->
        Map.put(map, key, value)
      end)
      Ecto.Schema.__load__(model, nil, nil, nil, fields,
                           &Ecto.Type.adapter_load(__adapter__, &1, &2))
    end)
  end

用法:

Repo.execute_and_load("SELECT * FROM users WHERE id = $1", [1], User)

更新:对于Ecto 3,您可以使用__MODULE__.load(model,fields)而不是Ecto.Schema.__load__

红朝
2023-03-14

在带有Postgres的Ecto 2.0(beta版)上,您可以使用<code>Ecto.Adapters.SQL。query()(当前文档,2.0-beta2文档)执行任意SQL;除了行本身的列表(“rows”)之外,它还碰巧返回了列名列表(“columns”)。

在下面的示例中,I

  1. 运行不带参数的自定义查询,
  2. 将结果的列名从字符串转换为原子,以及
  3. 将它们与结果的每一行合并,并使用 Kernel.struct() 将其映射到结构中

(您可能希望运行query()版本(没有爆炸!)并检查<code>{ok,res}</code>。)

qry = "SELECT * FROM users"
res = Ecto.Adapters.SQL.query!(Repo, qry, []) # 1

cols = Enum.map res.columns, &(String.to_atom(&1)) # 2

roles = Enum.map res.rows, fn(row) ->
  struct(MyApp.User, Enum.zip(cols, row)) # 3
end
 类似资料:
  • 问题内容: 这是课程: 现在,我试图从类中“反射”此方法: 问题答案: 只有一个。 另一种选择是。 其他原语也是如此。

  • 我试图实现,但没有成功。 现在我有了以下架构: 在类中,我有两个: 我希望在复选框中显示所有学科,并且希望当用户选择一个复选框时,将该复选框的对象学科添加到CourseDrimescies中-当取消选择一个复选框时,从CourseDiciplines中删除该学科。 我的JSF2.0代码如下: 这实际上显示了没有任何选中复选框的所有纪律,什么是正确的。但是当我选择一些复选框并提交表单时,我会尝试打印

  • 问题内容: 我知道这是一个基本问题,但是如果这个问题太愚蠢了,我似乎找不到答案,我很抱歉,但是我们开始: 我应该使用SQL Server(到目前为止没有问题)和Java(喜欢Java,这里也没问题),但是现在:我应该怎么做才能使组合起作用?我得到了: JRE 1.6 和 sqljdbc4.jar …在将sqljdbc4.jar放入我的类路径之前,我已经在其中添加了sqljdbc.jar并通过测试程

  • 我的目标是从一个id列表,我想更新保存的所有项目的字段为true,如果项目id属于id列表,false否则。 为什么第二个查询生成编译错误? 这是正确的方法吗?

  • 我在Ubuntu 14.04中安装了phpbrew以使用PHP5.4。它工作得很好,但当我尝试使用composer时除外,composer会忽略phpbrew并安装与PHP5.5相关的依赖项。 有没有办法强制composer与phpbrew config兼容?我试图在我的作曲家中添加:php:“5.4”。json,但是它说这个要求在我的php版本中是不可能的。

  • 我是Micronaut框架的新手,我正在尝试使用entitymanager创建我的存储库。我这样创建了我的存储库 我使用这个类实现接口并注入entitymanager 问题是我一直有这个错误: PS:我已经启用了注释处理