如何使ecto中的字段unique
?
我以为它与Ruby中的Active Record相同,但似乎并不是这样。
你想使用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
函数。
w(email)和w()是用来做什么的? - sheldonkregerunsafe_validate_unique
来近似实现此功能。它旨在“为用户提供快速反馈”,因此有时实现两者可能是有意义的。 - atomkirk