如何解决Elixir Ecto - 与 3 个或更多表的关联
如果我有 profile
,item
,location
表:
-
profile
有很多location
。 -
item
有一个location
。 -
location
和profile
中的item
不会重叠。
我应该如何设计 location
表?
以下有效吗? location
属于 2 个表?
schema "profiles" do
...
has_many :location,Location
end
schema "items" do
...
has_one :location,Location
end
schema "locations" do
...
belongs_to :profile,Profile
belongs_to :item,Item
end
还是应该有 2 个 location
表?
解决方法
这是一个非常主观的问题,取决于您将如何使用 locations
表中的数据。这通常是 polymorphic associations in Ecto 的推荐方法,具有额外的数据库约束,强制始终在位置记录上设置 profile_id
或 item_id
之一。
defmodule MyApp.Repo.Migrations.CreateLocations do
use Ecto.Migration
def change do
create table(:locations) do
add :profile_id,references(:profiles,on_delete: :delete_all)
add :item_id,references(:items,on_delete: :delete_all)
end
create constraint(:locations,:at_least_one_ref,check: "profile_id is not null or item_id is not null")
create index(:locations,[:profile_id,:item_id])
end
end
然后在变更集中,您可以验证此约束:
def changeset(location,attrs) do
location
|> cast(attrs,:item_id])
|> check_constraint(:profile_id,name: :at_least_one_ref)
end
另一种非常适用于 Ecto 但效果很好的方法,特别是因为您提到配置文件和项目之间没有位置重叠是使用使用 embeds_one 和 embeds_many 的嵌入式关联。如果您使用 Postgres,您甚至应该能够根据需要在 JSONB 列上创建索引。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。