是否可以使用 ecto 在同一个 entity/table 上实现多对多关联
Is it possible to implement Many-To-Many association on the same entity/table using ecto
我有一个具有唯一主键的用户 table,我想与另一个 User
实体建立 many-to-many
关联,以实现“社交网络”类型的事情。从这个 Many-to-many on same table 我知道这是可能的,但是我如何构建相同的 ecto
模式?
目前使用 join_through
as described here 和带有一些额外字段的模式来进一步定义关联,例如标志 blocked
以防用户阻止另一个用户,但我有在连接 table 上设置 has_many
的问题,因为这两种情况都指向相同的 User
模式。直到我开始怀疑 ecto 是否真的可行。
当然可以,你只需要指示Ecto如何到达相应的字段。
对于迁移
create table(:users) do
add(:name, :string)
end
create table(:friendship) do
add(:me_id, references("users"))
add(:friend_id, references("users"))
end
以及各自的模式
schema "users" do
field(:name, :string)
many_to_many(:users, User,
join_through: "friendship",
join_keys: [me_id: :id, friend_id: :id]
)
end
schema "friendship" do
field(:me_id, :integer)
field(:friend_id, :integer)
end
您可能会执行以下操作
iex|1> Repo.insert! %User{name: "john"}
iex|2> Repo.insert! %User{name: "mary"}
iex|3> Repo.insert! %Friendship{me_id: 1, friend_id: 2}
导致
iex|4> Repo.one(from u in User,
...|4> where: [id: 1], preload: [:users])
%User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 1,
name: "john",
users: [
%User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 2,
name: "mary",
users: #Ecto.Association.NotLoaded<association :users is not loaded>
}
]
}
我有一个具有唯一主键的用户 table,我想与另一个 User
实体建立 many-to-many
关联,以实现“社交网络”类型的事情。从这个 Many-to-many on same table 我知道这是可能的,但是我如何构建相同的 ecto
模式?
目前使用 join_through
as described here 和带有一些额外字段的模式来进一步定义关联,例如标志 blocked
以防用户阻止另一个用户,但我有在连接 table 上设置 has_many
的问题,因为这两种情况都指向相同的 User
模式。直到我开始怀疑 ecto 是否真的可行。
当然可以,你只需要指示Ecto如何到达相应的字段。
对于迁移
create table(:users) do
add(:name, :string)
end
create table(:friendship) do
add(:me_id, references("users"))
add(:friend_id, references("users"))
end
以及各自的模式
schema "users" do
field(:name, :string)
many_to_many(:users, User,
join_through: "friendship",
join_keys: [me_id: :id, friend_id: :id]
)
end
schema "friendship" do
field(:me_id, :integer)
field(:friend_id, :integer)
end
您可能会执行以下操作
iex|1> Repo.insert! %User{name: "john"}
iex|2> Repo.insert! %User{name: "mary"}
iex|3> Repo.insert! %Friendship{me_id: 1, friend_id: 2}
导致
iex|4> Repo.one(from u in User,
...|4> where: [id: 1], preload: [:users])
%User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 1,
name: "john",
users: [
%User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
id: 2,
name: "mary",
users: #Ecto.Association.NotLoaded<association :users is not loaded>
}
]
}