在 ecto 中使一个字段成为唯一的。

41

如何使ecto中的字段unique

我以为它与Ruby中的Active Record相同,但似乎并不是这样。

1个回答

78

你想使用unique_constraint/3。与Active Record不同的是,它使用数据库来确保唯一性。Active Record将查询具有相同值的记录,如果返回任何记录,则会失败。这会产生竞争条件,如果在获取检查唯一性和插入记录之间插入一个值,则最终会出现重复数据或引发错误(取决于数据库是否设置了索引)。而unique_constraint/3就没有这个问题。

值得注意的是,由于唯一性直到尝试插入时才知道,因此唯一约束将在您的验证之后发生。无法同时显示验证和约束错误。

您使用的数据库也必须支持唯一约束。在SQLite中它们不起作用。您可以在[GitHub问题]https://github.com/elixir-lang/ecto/issues/865中阅读更多相关信息。

当使用SQLite3数据库时,您只需要使用ecto3_sqlite3适配器,唯一约束将按预期工作。

将以下内容添加到您的mix.exs文件:

{:ecto_sqlite3, "~> 0.7.7"},

在您的迁移中:

create unique_index(:users, [:email])

那么在您的模型中:

cast(user, params, ~w(email), ~w())
|> unique_constraint(:email)

值得注意的是,Ecto曾经提供过一个validate_unique/3函数,它通过对数据库进行查询来工作,但是它已被弃用,推荐使用unique_constraint/3函数。


嗨,它导致了另一个错误https://dev59.com/zo7ea4cB1Zd3GeqPHemR - ardhitama
1
w(email)和w()是用来做什么的? - sheldonkreger
~w(...) 语法创建一个列表。http://elixir-lang.org/docs/stable/elixir/Kernel.html#sigil_w/2 - Gazler
上面评论中的Sigil链接已经失效了。这里是一个可用的链接:https://elixir-lang.org/getting-started/sigils.html#word-lists - Sgnl
无法同时显示验证和约束错误。Ecto提供了unsafe_validate_unique来近似实现此功能。它旨在“为用户提供快速反馈”,因此有时实现两者可能是有意义的。 - atomkirk
我认为为Ruby提供相关的“唯一性”文档链接也是很好的:https://guides.rubyonrails.org/active_record_validations.html#uniqueness - Burak Kaymakci

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接