Typegraphql + TypeORM: lưu / cập nhật một mảng thực thể
Tôi có một máy chủ graphql và một rolebảng, và tôi muốn lưu nhiều vai trò trong một đột biến.
Tôi đã tìm kiếm rất nhiều nhưng không tìm thấy gì.
Làm thế nào tôi có thể làm một cái gì đó như:
mutation {
addRoles (roles: [
{
name: "role1",
description: "role 1"
},
{
name: "role2",
description: "role 2"
},
...
])
}
Nói cách khác, làm thế nào để thực hiện addRolesvà updateRolesgiải quyết?
Vòng lặp for có phải là lựa chọn duy nhất không? Có thể lưu tất cả các vai trò trong một lệnh gọi DB không?
Các rolemô hình:
@Entity("role")
@ObjectType()
export class Role extends BaseEntity {
@Field((type) => Number)
@PrimaryGeneratedColumn()
readonly id!: number;
@Field()
@Column({ length: 64 })
name!: string;
@Field({ nullable: true })
@Column({ length: 512, nullable: true })
description!: string;
}
Và thêm và cập nhật trình giải quyết:
@Resolver((of) => Role)
export class RoleResolver {
@Mutation((returns) => Boolean)
async addRole(
@Arg("role") role: AddRoleInput
): Promise<Boolean> {
const roleExists = await Role.count({ name: role.name });
if (roleExists > 0)
throw new Error(`Role with name "${role.name}" already exists!`);
const newRole = Role.create(role);
await newRole.save();
return true;
}
@Mutation((returns) => Boolean)
async updateRole(
@Arg("role") role: UpdateRoleInput
): Promise<Boolean> {
const oldRole = await Role.findOneOrFail(role.id);
Object.assign(oldRole, role);
await oldRole.save();
return true;
}
}
Và AddRoleInputvàUpdateRoleInput
@InputType({ description: "New Role Argument" })
export class AddRoleInput implements Partial<Role> {
@Field()
name!: string;
@Field({ nullable: true })
description?: string;
}
@InputType({ description: "Update Role Argument" })
export class UpdateRoleInput implements Partial<Role> {
@Field()
id!: number;
@Field()
name!: string;
@Field({ nullable: true })
description?: string;
}
Trả lời
Ý chính của những gì bạn cần làm là xác định một addRolestrường trên loại Mutation trong lược đồ của bạn. Ví dụ
export const RoleSchema = gql`
type Role {
id: Int
# Other fields omitted for brevity
}
extend type Mutation {
# This should already exist
addRole(role: AddRoleInput!): Role!
# To accept multiple Input Types, use the List construct
addRoles(roles: [AddRoleInput!]!): [Role!]
}
`;
Sau đó, xác định addRolestrong trình phân giải của bạn và gọi API thích hợp.
Tôi đã cố gắng tìm ra câu trả lời bằng cách thử và sai. Tôi sẽ đăng nó ở đây trong trường hợp ai đó gặp vấn đề tương tự:
@Resolver((of) => Role)
export class RoleResolver {
@Mutation((returns) => Boolean)
async addRoles(
@Arg("roles", type => [AddRoleInput]) roles: AddRoleInput[]
): Promise<Boolean> {
// also checks at front
const roleExists = await Role.count({
name: In(roles.map((role) => role.name)),
});
if (roleExists > 0)
throw new Error(`Role name conflict!`);
const newRoles = []
for (let i=0, i < roles.length, i++) {
const newRole = Role.create(roles[i]);
newRoles.push(newRole);
}
// this is the solution
// turns out an entity class can be used to save instances
// failed to found this in the docs though
await Role.save(newRoles);
return true;
}
...
}
Tôi sẽ giữ tiền thưởng mở trong trường hợp có câu trả lời tốt hơn.