elixir - 在 Ecto 迁移中使用 Repo

标签 elixir database-migration ecto

我有一个 Ecto 迁移,我想修改一些列,但也迁移一些数据。例如:

import Ecto.Query

defmodule MyApp.Repo.Migrations.AddStatus do
  alter table(:foo) do
    add(:status, :text)
  end

  foos = from(f in MyApp.Foo, where: ...)
         |> MyApp.Repo.all

  Enum.each(foos, fn(foo) ->
    # There's then some complex logic here to work 
    # out how to set the status based on other attributes of `foo`
  end)
end

现在,这里的问题是通过调用 MyApp.Repo.all迁移本质上使用单独的数据库连接到 alter table...使用的语句( 编辑 :此假设是错误的,请参阅已接受的答案)。因此,没有 status列所以整个迁移爆炸了!请注意,我们使用的是 postgres数据库,因此 DDL 语句是事务性的。

我可以将其作为两个单独的迁移或 mix 来完成。任务来设置数据,只为架构更改留下迁移,但为了确保数据一致性,不希望这样做。

关于如何为 MyApp.Repo 使用相同的数据库连接的任何想法以这种方式查询?

编辑 :请注意,我正在处理一小组数据,在我的用例中,停机时间是可以接受的。如果情况并非如此,请参阅下面 José 的回复以获取一些好的建议。

最佳答案

一般来说,同时进行数据迁移和更改 DDL 是一种不好的做法。如果这是一个实时系统并且迁移需要很长时间,您可能会在很长一段时间内产生大量争用。

如果您的应用程序仍在处理请求,则可以在处理数据时添加新条目,而不会处理这些条目!

有不同的方法来解决这个问题,具体取决于用例,但它们通常需要循序渐进的方法。例如,如果您要添加一个新列:

  • 第一步是在数据库中引入新列,并确保在创建新条目时填充新列。这一步只是为了保证所有 future 的条目都将被正确填充。
  • 那么第二步就是迁移旧数据
  • 最后,您可以让新数据生效,因为您可以假设所有条目都已正确填充
  • 关于elixir - 在 Ecto 迁移中使用 Repo,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48381568/

    相关文章:

    elixir - 在 Elixir 列表中,如何获得中间值?

    protocols - 如何避免协议(protocol)的透析器错误?

    scala - 关注 Play 的演变?

    c# - 使用 ColumnAttribute 或 HasKey 方法指定复合主键的顺序

    python - mysql-connector-python cursor_cent.py 文件上的 Django 迁移错误 'TypeError: sequence item 1: expected a bytes-like object, str found'

    elixir - 在 Ecto 中构建动态片段

    elixir - Ecto.Queryable 未针对用户/Phoenix 错误实现

    database - 如何验证映射字段在 Ecto 模型(而不是 Controller )中是否具有特定键?

    logging - 用于列表、元组等的 elixir Logger

    mongodb - ChangeSet Ecto.Model Struct 的所有字段均为零