且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在Ecto迁移中动态更新字段值?

更新时间:2023-12-01 13:46:46

您将要进行两个单独的查询。第一个查询获取数据,执行所需的任何更改,然后第二个查询更新该数据。

You are going to want to make two separate queries. One query to grab the data, do whatever changes you want, then a second query to update that data. Something along the lines of

Repo.all(MyApp.User)
|> Enum.map(fn u ->
  username = 
    u.email
    |> String.split("@")
    |> List.first()

  Ecto.Changeset.cast(u, %{username: username})
end)
|> Repo.update_all()

关于为什么您不能做自己的事情有两件事

There are a couple things going on as to why you cannot do what you were attempting to do.

当您想在Ecto查询中使用Elixir函数或值时,通常必须使用pin运算符( ^ )。因此,如果要查询特定的ID,可以使用 from(MyApp.User中的u,其中:u.id == ^ 12)。因此,您的反应可能是尝试使用 ^ List.first(String.split(u.email, @))。但是,这将不起作用,因为...

When you want to use an Elixir function or value within an Ecto query, you would normally have to use the pin operator (^). So if you wanted to query for a specific ID, you could use from(u in MyApp.User, where: u.id == ^12). So your reaction may be to try and use ^List.first(String.split(u.email, "@")). However, this will not work because...

中的 u from(u (在MyApp.User中)是数据库中的记录。您无法在Elixir代码中访问它。可能可以使用 fragment / 1 进行操作,但是您无法使用常规的Elixir函数操纵该值,直到您使用上述示例将其实际从数据库中拉出为止。

The u in from(u in MyApp.User) is the record as is in the database. You do not have access to it in your Elixir code. It may be possible to use a fragment/1 for what you are trying to do, but you cannot manipulate the value with regular Elixir functions until you actually pull it out of the database using something like my example above.