如何使用片段作为更新变更集属性的一部分?

Joo*_*nas 1 elixir ecto phoenix-framework

我正在尝试使用新属性和与现有列交互的数据库调用来更新现有模型。类似于UPDATE companies SET a = 1, b = jsonb_set(b, '{key}', CURRENT_TIMESTAMP(), true)SQL 中的东西。

我如何使用 Ecto 和片段来实现这一目标?

这是我的尝试,但它失败了,因为它fragment是一个宏:

enhanced =
  %{ attrs | b: fragment(
    "jsonb_set(b, ?, CURRENT_TIMESTAMP(), true)",
    "{#{Atom.to_string(key)}}"
  )}
result =
  company
  |> Company.changeset(enhanced)
  |> Repo.update()
Run Code Online (Sandbox Code Playgroud)

小智 6

使用片段宏 viaEcto.Query.update是正确的方法。为此,我们需要将更新作为查询表达式

\n\n
{count, results} =\n  Company\n  |> where([c], <some_condition>)\n  |> select([e], e) ## Optional: this will return our changes\n  |> update(set: [\n        string_field: "value",\n        map_field: fragment(~S<jsonb_set("map_field"::jsonb, \'{key_name_here}\', \'value_here\')>)\n      ]\n  |> Repo.update_all([])\n
Run Code Online (Sandbox Code Playgroud)\n\n

用于~S<\xe2\x80\xa6>避免转义引号"片段中的引号。

\n\n

通过将字符串中的变量替换为 a?并将它们添加为固定变量,将变量添加到片段中^片段中。

\n\n
fragment(~S<jsonb_set("map_field"::jsonb, \'{?}\', \'value_here\')>, ^key)\n
Run Code Online (Sandbox Code Playgroud)\n