我想创建一个包含3个字段的unique_constraint,并将其称为“ unique_user_product_shop”。当我这样做时,我的数据库抛出一个错误,表明尝试的插入不是唯一的:
错误:
18:04:18.830 [error] #PID<0.380.0> running Api.Router terminated
Server: 192.168.1.12:4000 (http)
Request: PUT /product/isinshop/?p_id=12&s_id=12&u_id=792200324272726
** (exit) an exception was raised:
** (FunctionClauseError) no function clause matching in Ecto.Changeset.add_constraint/6
(ecto) lib/ecto/changeset.ex:2272: Ecto.Changeset.add_constraint(#Ecto.Changeset<action: nil, changes: %{p_id: 12, s_id: 12, u_id: "792200324272726", voted_in_shop: true, voted_not_in_shop: false}, errors: [], data: #Api.UserProductShop<>, valid?: true>, :unique, "unique_user_product_shop", :exact, [:p_id, :u_id, :s_id], {"has already been taken", []})
(api) lib/api/models/user_product_shop.ex:37: Api.UserProductShop.insert_user_product_shop/2
(api) lib/api/controllers/product/put_product_is_in_shop.ex:48: Api.Controllers.PutProductIsInShop.put_product_is_in_shop/1
(api) lib/api/router.ex:1: Api.Router.plug_builder_call/2
(api) lib/plug/debugger.ex:123: Api.Router.call/2
(plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
(cowboy) /Users/Ben/Development/Projects/vepo/api/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4
我的代码:
def changeset(user_product_shop, params \\ %{}) do
user_product_shop
|> cast(params, [
:u_id,
:p_id,
:s_id,
:voted_not_in_shop,
:voted_in_shop])
|> validate_required([:u_id, :p_id, :s_id])
|> unique_constraint([:p_id, :u_id, :s_id], name: :unique_user_product_shop)
end
那为什么不选择我的unique_constraint导致我的数据库在控制台中抛出红色错误?
答案 0 :(得分:7)
Ecto.Changeset.unique_constraint/3
必须由real unique constraint in the database备份。这是文档摘录:
为了使用唯一性约束,第一步是在迁移中定义唯一索引:
create unique_index(:users, [:email])
Ecto.Changeset.unique_constraint/3
仅用于模式匹配现有的唯一约束,这就是为什么如果数据库中没有这样的约束,则会引发FunctionClauseError
。