如何将 Ecto.Enum 与 postgres ENUM 类型一起使用?

cjm*_*671 2 elixir ecto

根据文档: https: //hexdocs.pm/ecto/Ecto.Enum.html

看来我应该将我的迁移构建为:

add :status, :string
Run Code Online (Sandbox Code Playgroud)

问题是,这没有利用 Postgres ENUM 类型https://www.postgresql.org/docs/current/datatype-enum.html#id-1.5.7.15.5

拥有 ENUM 的主要目的是减少字段的存储占用空间。

我应该如何构建迁移以利用 Postgres 内置的 ENUM,还是应该使用不同的方法?

sab*_*ara 5

正如文档中提到的,Ecto.Enum实际上也可以与 ENUM 类型一起使用:

有些数据库还支持枚举类型,您可以将其与上述类型结合使用。

AFAIK,虽然没有迁移功能,但你需要用 SQL 编写它:

execute("CREATE TYPE my_status AS ENUM ('todo', 'wip', 'done');")

create_table :tasks do
  ...
  add :status, :my_status, null: false
  ...
end
Run Code Online (Sandbox Code Playgroud)

拥有 ENUM 的主要目的是减少字段的存储占用空间。

Ecto.Enum即使与string字段一起使用也有很多优点:

  • 验证您的架构、应用程序端
  • 处理原子转换
  • 当处理已知值时,使用原子比字符串更好,与类型规范和透析器配合得很好

此外,在数据库端使用 ENUM 类型也有缺点,我想这就是为什么它没有在文档中得到更多推动的原因。更新枚举类型以添加​​/修改/字段可能很棘手,并且会带来风险,正如《SQL Antipatterns》一书中所解释的那样,如果值稍后可能发生更改,该书建议不要这样做。

为了减少存储占用,还有第三种选择,即将其存储为整数。引用文档:

# in migration:
add :status, :integer

# in schema:
field :status, Ecto.Enum, values: [foo: 1, bar: 2, baz: 5]
Run Code Online (Sandbox Code Playgroud)