Multiple many_to_many with same models?

I need 3 many-to-many references (with timestamps) to same model and table, but with different names.
When I try to insert association to one of many_to_many relation it adds to all (:firsts, :seconds and :thirds).

Models:

defmodule Example.Sample do
  use Ecto.Schema
  
  schema "samples" do
    many_to_many :firsts, Example.Something, join_keys: [sample_id: :id, something_id: :id], join_through: Example.SomethingSample, on_delete: :delete_all
    many_to_many :seconds, Example.Something, join_keys: [sample_id: :id, something_id: :id], join_through: Example.SomethingSample, on_delete: :delete_all
    many_to_many :thirds, Example.Something, join_keys: [sample_id: :id, something_id: :id], join_through: Example.SomethingSample, on_delete: :delete_all
    timestamps
  end
end

defmodule Example.Something do
  use Ecto.Schema
  
  schema "somethings" do
    many_to_many :samples, Example.Sample, join_keys: [something_id: :id, sample_id: :id], join_through: Example.SomethingSample, on_delete: :delete_all
    timestamps
  end
end

defmodule Example.SomethingSample do
  use Ecto.Schema
  
  schema "sample_somethings" do
    belongs_to :sample, Example.Sample
    belongs_to :something, Example.Something
    timestamps
  end
end

Migration:

defmodule Example.Repo.Migrations.AddAll do
  use Ecto.Migration
  
  def change do
    create table(:samples) do
      timestamps
    end
    
    create table(:somethings) do
      timestamps
    end
    
    create table(:sample_somethings) do
      add :sample_id, references(:samples, on_delete: :delete_all)
      add :something_id, references(:somethings, on_delete: :delete_all)
      timestamps
    end
  end
end

What is the best way to solve this?

If they all join to the same foreign key then they will always be the same list. You need them to join to different keys, otherwise how could you differentiate them. :slight_smile:

Yes, I think about more models (with tables) like: “SomethingSample” or multiple foreign keys in that model.
I just asked about “good practice”, because it is possible that in ecto is implemented other way, which I don’t know and is for example more readable for developers using ecto.
Anyway, thanks for sharing knowledge :smile:.