Elixir Ecto 同时进行一对多和一对一

问题描述 投票:0回答:1

我有 2 个具有一对多关系的表/模式,假设有一个

Person
可以有多个
Animal
。然后每个动物都有人外键来实现这种关系。我将 Elixir 与 Ecto 一起使用,所以现在很简单,我已经

schema "persons" do
  ...
  has_many :animals, Animal
end

schema "animals" do
  ...
  belongs_to :person, Person
end

我想引入一个人最喜欢的动物的概念,每个人最多可以有 1 个最喜欢的动物(0 或 1)。当两个表之间已经存在一对多关系时,如何实现第二个关系?

我想到了两种替代解决方案,但都不是完美的。

  1. 不要引入一对一,但在 Animal 中还有另一个名为

    favourite
    的字段,具有 true 或 false。这是一个简单的解决方案,但缺乏数据库强制执行最多 1 个最喜欢的动物,因为数据库中同一个人的多个动物有可能拥有
    favourite: true
    ,因此需要在业务逻辑中手动保留此约束并持续观察为了它。

  2. 引入一对一的关系。 Animal已经有了person_id_fkey,现在我需要将animal_id_fkey添加到Person中,表示该人最喜欢的动物。直觉告诉我那个人

    has_one
    最喜欢动物,但在Ecto中我们使用
    belongs_to
    来引入外键,所以如下。

  ...
  has_many :animals, Animal
  belongs_to :favourite_animal, Animal
end

schema "animals" do
  ...
  belongs_to :person, Person
  has_one :person, Person <- this name must be different due to conflict
end 

动词表明该人属于动物,但现实却截然不同。字段名称也存在歧义——人有最喜欢的动物,但是这个字段

has_one Person
应该如何命名?我不清楚,因为第二个场景中出现了越来越多的问题。

Ecto(或更普遍的 SQL)中解决此类双向外键关系的惯用方法是什么?

sql database-design elixir ecto
1个回答
0
投票

我无法立即测试它,因此我将其发布为答案只是为了格式化。如果它不适合您,请随意投反对票。

动词不会骗你,只需使用

belongs_to/3
和适当的选项即可。

schema "persons" do
  has_many :animals, Animal
  has_one :favorite, Animal
end

schema "animals" do
  belongs_to :person, Person, foreigh_key: :owner_id, references: :id
  belongs_to :person, Person, foreign_key: :favorite_of_id, references: :id
end
© www.soinside.com 2019 - 2024. All rights reserved.