在 Ecto 的“belongs_to”关联中引用复合键?
Reference a composite key in a `belongs_to` association in Ecto?
我正在尝试将一个实体 A 建模为仅附加实体,另一个子实体引用第一个实体。所以 A 的结构类似于(按 inserted_at DESC
排序):
| id | version | column | inserted_at |
|------|-----------+---------|-------------|
| 5 | 2 | "baz" | 2020-04-20 |
| 3 | 2 | "zoot" | 2020-04-20 |
| 3 | 1 | "bar " | 2020-04-18 |
| 5 | 1 | "foo" | 2020-04-10 |
(id, version)
构成 A 的主键(也可以 (id, inserted_at)
,但开发人员认为版本号更具可读性)。
现在 B 属于 A,每个 B 将恰好对应 (id, version)
对 A。所以类似:
| id | a_id | a_version | column | inserted_at |
|------|-------+-----------+---------+-------------|
| 4 | 5 | 2 | "pigs" | 2020-05-05 |
| 3 | 5 | 2 | "goats"| 2020-05-03 |
| 2 | 5 | 1 | "rams" | 2020-05-02 |
| 1 | 3 | 1 | "bears"| 2020-04-18 |
我的问题是,如何使用 Ecto Schemas 对这些进行建模?我想我通过阅读文档知道 A 模式是什么样的,除了 has_many
:
defmodule MyASchema do
use Ecto.Schema
@primary_key false
schema "table_a" do
field :id, :id, primary_key: true
field :version, :integer, primary_key: true
field :column, :string
field :inserted_at, :utc_datetime
has_many :bs, MyBSchema # what goes here for :foreign_key?
end
end
但是 B 模式(尤其是 belongs_to
)我不太清楚:
defmodule MyBSchema do
use Ecto.Schema
@primary_key
schema "table_b" do
field :id, :id, primary_key: true
field :column, :string
field :inserted_at, :utc_datetime
# how does belongs_to work here? would it be
#
# belongs_to :a, MyASchema, primary_key: [:id, :version]
#
# or
#
# belongs_to :a, MyASchema, define_key: false
# field :a_id, :id
# field :a_version, :integer
#
# ? If so, how could I query such that the :a field of the
# struct is populated?
end
end
很高兴进一步澄清,感谢阅读+任何帮助
根据 Elixir forum,Ecto 在使用关联时不支持复合外键。
一个解决方案是添加一个 "regular" 唯一的主键(例如,一个自动递增的整数或 UUID)并基于该 ID 进行引用。有时您在使用数据库抽象层时会感到安慰,因为当数据库具有简单的单列主键(即不是组合)时,关系更容易定义。
如果无法更改数据库架构,则您需要手动解析代码中的关联。您可能需要设置多个事务,如 .
所述
我正在尝试将一个实体 A 建模为仅附加实体,另一个子实体引用第一个实体。所以 A 的结构类似于(按 inserted_at DESC
排序):
| id | version | column | inserted_at |
|------|-----------+---------|-------------|
| 5 | 2 | "baz" | 2020-04-20 |
| 3 | 2 | "zoot" | 2020-04-20 |
| 3 | 1 | "bar " | 2020-04-18 |
| 5 | 1 | "foo" | 2020-04-10 |
(id, version)
构成 A 的主键(也可以 (id, inserted_at)
,但开发人员认为版本号更具可读性)。
现在 B 属于 A,每个 B 将恰好对应 (id, version)
对 A。所以类似:
| id | a_id | a_version | column | inserted_at |
|------|-------+-----------+---------+-------------|
| 4 | 5 | 2 | "pigs" | 2020-05-05 |
| 3 | 5 | 2 | "goats"| 2020-05-03 |
| 2 | 5 | 1 | "rams" | 2020-05-02 |
| 1 | 3 | 1 | "bears"| 2020-04-18 |
我的问题是,如何使用 Ecto Schemas 对这些进行建模?我想我通过阅读文档知道 A 模式是什么样的,除了 has_many
:
defmodule MyASchema do
use Ecto.Schema
@primary_key false
schema "table_a" do
field :id, :id, primary_key: true
field :version, :integer, primary_key: true
field :column, :string
field :inserted_at, :utc_datetime
has_many :bs, MyBSchema # what goes here for :foreign_key?
end
end
但是 B 模式(尤其是 belongs_to
)我不太清楚:
defmodule MyBSchema do
use Ecto.Schema
@primary_key
schema "table_b" do
field :id, :id, primary_key: true
field :column, :string
field :inserted_at, :utc_datetime
# how does belongs_to work here? would it be
#
# belongs_to :a, MyASchema, primary_key: [:id, :version]
#
# or
#
# belongs_to :a, MyASchema, define_key: false
# field :a_id, :id
# field :a_version, :integer
#
# ? If so, how could I query such that the :a field of the
# struct is populated?
end
end
很高兴进一步澄清,感谢阅读+任何帮助
根据 Elixir forum,Ecto 在使用关联时不支持复合外键。
一个解决方案是添加一个 "regular" 唯一的主键(例如,一个自动递增的整数或 UUID)并基于该 ID 进行引用。有时您在使用数据库抽象层时会感到安慰,因为当数据库具有简单的单列主键(即不是组合)时,关系更容易定义。
如果无法更改数据库架构,则您需要手动解析代码中的关联。您可能需要设置多个事务,如