many_to_many批次insert/update
many_to_many batch insert/update
我正在尝试找出保存具有 many_to_many 关系的结构的最佳方法。
假设我有 user
和 role
架构是按以下方式创建的:
迁移:
def change do
create table(:users) do
add :email, :string
add :username, :string
end
create table(:roles) do
add :name, :string, null: false
end
create table(:users_roles, primary_key: false) do
add :user_id, references(:users, on_delete: :delete_all)
add :role_id, references(:roles, on_delete: :delete_all)
end
create unique_index(:users, [:email, :username]
create unique_index(:roles, [:name])
create unique_index(:users_roles, [:user_id, :role_id])
end
用户架构:
schema "users" do
field :email, :string
field :username, :string
many_to_many :roles, TimesheetServer.Role, join_through: "users_roles"
end
def changeset(struct, params \ %{}) do
struct
|> cast(params, [:email, :username])
|> validate_required([:email, :username])
end
end
角色模式:
schema "roles" do
field :name, :string
many_to_many :users, TimesheetServer.User, join_through: "users_roles"
end
def changeset(struct, params \ %{}) do
struct
|> cast(params, [:name])
|> validate_required([:name])
end
end
将单个角色与用户关联时,关联没有问题。但是,当涉及到在一个请求中关联多个角色时,我只想到了以下解决方案:
更新用户端点:/api/users/{user_id}
请求正文:
{
"roles": [
{"id": 10},
{"id": 2},
{"id": 1}
]
}
用户变更集:
def changeset(struct, params \ %{}) do
struct
|> cast(params, [:email, :username])
|> validate_required([:email, :username])
|> put_assoc(:roles, cast_roles(params))
end
defp cast_roles(params) do
%{"roles" => roles} = params
Enum.map(roles, fn role -> get_role(role) end)
end
defp get_role(role) do
%{"id" => id} = role
Repo.get!(Role, id)
end
确实有效,协会已更新。我担心的是我必须遍历角色并对每个角色进行数据库请求。还有其他方法可以达到同样的效果吗?
您可以为指向 users_roles
table 的关联创建一个 module/schema,然后只需插入一个 %UserRole{}
结构来在 [=] 之间创建一个关联15=] 和 Role
。这样您也可以使用 Repo.insert_all
进行批量插入。
defmodule MyApp.UserRole do
...
schema "users_roles" do
belongs_to :user, User
belongs_to :role, Role
end
end
Repo.insert! %MyApp.UserRole{user_id: 123, role_id: 456}
或
Repo.insert_all! MyApp.UserRole, [%{user_id: 1, role_id: 1},
%{user_id: 2, role_id: 1},
%{user_id: 2, role_id: 2}]
我正在尝试找出保存具有 many_to_many 关系的结构的最佳方法。
假设我有 user
和 role
架构是按以下方式创建的:
迁移:
def change do
create table(:users) do
add :email, :string
add :username, :string
end
create table(:roles) do
add :name, :string, null: false
end
create table(:users_roles, primary_key: false) do
add :user_id, references(:users, on_delete: :delete_all)
add :role_id, references(:roles, on_delete: :delete_all)
end
create unique_index(:users, [:email, :username]
create unique_index(:roles, [:name])
create unique_index(:users_roles, [:user_id, :role_id])
end
用户架构:
schema "users" do
field :email, :string
field :username, :string
many_to_many :roles, TimesheetServer.Role, join_through: "users_roles"
end
def changeset(struct, params \ %{}) do
struct
|> cast(params, [:email, :username])
|> validate_required([:email, :username])
end
end
角色模式:
schema "roles" do
field :name, :string
many_to_many :users, TimesheetServer.User, join_through: "users_roles"
end
def changeset(struct, params \ %{}) do
struct
|> cast(params, [:name])
|> validate_required([:name])
end
end
将单个角色与用户关联时,关联没有问题。但是,当涉及到在一个请求中关联多个角色时,我只想到了以下解决方案:
更新用户端点:/api/users/{user_id}
请求正文:
{
"roles": [
{"id": 10},
{"id": 2},
{"id": 1}
]
}
用户变更集:
def changeset(struct, params \ %{}) do
struct
|> cast(params, [:email, :username])
|> validate_required([:email, :username])
|> put_assoc(:roles, cast_roles(params))
end
defp cast_roles(params) do
%{"roles" => roles} = params
Enum.map(roles, fn role -> get_role(role) end)
end
defp get_role(role) do
%{"id" => id} = role
Repo.get!(Role, id)
end
确实有效,协会已更新。我担心的是我必须遍历角色并对每个角色进行数据库请求。还有其他方法可以达到同样的效果吗?
您可以为指向 users_roles
table 的关联创建一个 module/schema,然后只需插入一个 %UserRole{}
结构来在 [=] 之间创建一个关联15=] 和 Role
。这样您也可以使用 Repo.insert_all
进行批量插入。
defmodule MyApp.UserRole do
...
schema "users_roles" do
belongs_to :user, User
belongs_to :role, Role
end
end
Repo.insert! %MyApp.UserRole{user_id: 123, role_id: 456}
或
Repo.insert_all! MyApp.UserRole, [%{user_id: 1, role_id: 1},
%{user_id: 2, role_id: 1},
%{user_id: 2, role_id: 2}]