是否可以使用 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>
    }
  ]
}