I am learning Ecto and was trying out many to many relationship.
I am using MySQL DB,
方案是这样的
用户架构
@primary_key {:id, :binary_id, autogenerate: true}
schema "users" do
field(:name, :string, required: true)
field(:hashed_password, :string, required: true)
field(:password, :string, virtual: true)
timestamps()
many_to_many(:methods, Bookie.Method.Model, join_through: "users_methods", on_replace: :delete)
end
方法架构
@primary_key {:id, :binary_id, autogenerate: true}
schema "methods" do
field(:function, :string, required: true)
field(:method, :string, required: true)
timestamps()
many_to_many(:users, Bookie.User.Model, join_through: "users_methods", on_replace: :delete)
end
这2个方案的关联-users_methods
schema "users_methods" do
belongs_to(:users, Bookie.User.Model, type: :binary_id)
belongs_to(:methods, Bookie.Method.Model, type: :binary_id)
end
这些是我的迁移
create table(:users, primary_key: false) do
add(:id, :uuid, primary_key: true)
add(:name, :string, null: false)
add(:hashed_password, :string, null: false)
timestamps()
end
create(unique_index(:users, [:name]))
create table(:methods, primary_key: false) do
add(:id, :uuid, primary_key: true)
add(:function, :string, null: false)
add(:method, :string, null: false)
timestamps()
end
create table(:users_methods, primary_key: false) do
add(:user_id, references("users", type: :uuid, on_delete: :delete_all))
add(:method_id, references("methods", type: :uuid, on_delete: :delete_all))
end
create(index(:users_methods, [:method_id]))
create(index(:users_methods, [:user_id]))
create(
unique_index(:users_methods, [:user_id, :method_id], name: :user_id_method_id_unique_index)
)
这是我的基本设置。现在,一旦我在查询/插入用户后尝试预加载方法,就会给我错误。
user_map = %{name: "User 1", password: "password"}
changeset =
User.changeset(%User{}, user_map)
|> Ecto.Changeset.put_change(
:hashed_password,
User.hashed_password(changeset.changes[:password])
)
user =
Repo.insert!(changeset)
|> Repo.preload(:methods)
错误
[debug] QUERY OK db=2.6ms queue=0.1ms
begin []
[debug] QUERY OK db=3.5ms
INSERT INTO `users` (`hashed_password`,`name`,`inserted_at`,`updated_at`,`id`) VALUES (?,?,?,?,?) ["$2b$12$6W3zoeCnfLRV3N0fzv5t..LFnZly93G4IvfM5DfQSaEWPLtK0jV8q", "User 1", {{2019, 6, 8}, {14, 29, 25, 458464}}, {{2019, 6, 8}, {14, 29, 25, 458477}}, <<208, 210, 137, 42, 54, 3, 75, 211, 148, 173, 9, 174, 171, 125, 44, 225>>]
[debug] QUERY OK db=0.7ms
commit []
[debug] QUERY ERROR source="methods" db=29.5ms
SELECT m0.`id`, m0.`function`, m0.`method`, m0.`inserted_at`, m0.`updated_at`, u1.`id` FROM `methods` AS m0 INNER JOIN `users` AS u1 ON u1.`id` IN (?) INNER JOIN `users_methods` AS u2 ON u2.`model_id` = u1.`id` WHERE (u2.`model_id` = m0.`id`) ORDER BY u1.`id` [<<208, 210, 137, 42, 54, 3, 75, 211, 148, 173, 9, 174, 171, 125, 44, 225>>]
** (Mariaex.Error) (1054): Unknown column 'u2.model_id' in 'where clause'
(ecto) lib/ecto/adapters/sql.ex:450: Ecto.Adapters.SQL.sql_call!/6
(ecto) lib/ecto/adapters/sql.ex:420: Ecto.Adapters.SQL.do_execute/6
(ecto) lib/ecto/repo/queryable.ex:133: Ecto.Repo.Queryable.execute/5
(ecto) lib/ecto/repo/queryable.ex:37: Ecto.Repo.Queryable.all/4
(elixir) lib/enum.ex:1327: Enum."-map/2-lists^map/1-0-"/2
(Mariaex.Error)(1054):“ where子句”中的未知列“ u2.model_id”
我没有超越:(
请帮助。
答案 0 :(得分:1)
关联外键从模式名称的最后一部分开始变化。由于您的所有架构都命名为Foo.Bar.Model
,因此它们都默认为model_id
。您可以通过join_keys
选项来指定关系。
例如:
many_to_many(:methods, Bookie.Method.Model, join_through: "users_methods", on_replace: :delete)
应为:
many_to_many(:methods, Bookie.Method.Model, join_through: "users_methods", join_keys: [user_id: :id, method_id: :id], on_replace: :delete)
并且:
many_to_many(:users, Bookie.User.Model, join_through: "users_methods", on_replace: :delete)
应该是:
many_to_many(:users, Bookie.User.Model, join_through: "users_methods", join_keys: [method_id: :id, user_id: :id], on_replace: :delete)
尽管我建议遵循Ecto的命名约定,但是一切都会变得更加简单。