Typegraphql + TypeORM: simpan / perbarui array entitas

Oct 05 2020

Saya memiliki server graphql dan roletabel, dan saya ingin menyimpan banyak peran dalam satu mutasi.

Saya mencari banyak tetapi tidak menemukan apa pun.

Bagaimana saya bisa melakukan sesuatu seperti:

mutation {
  addRoles (roles: [
    {
      name: "role1",
      description: "role 1"
    },
    {
      name: "role2",
      description: "role 2"
    },
    ...
  ])
}

Dengan kata lain, bagaimana mengimplementasikan addRolesdan updateRolesmenyelesaikan?

Apakah for loop satu-satunya pilihan? Apakah mungkin untuk menyimpan semua peran dalam satu panggilan DB?

The roleModel:

@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;
}

Dan tambahkan dan perbarui resolver:

@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;
  }
}

Dan AddRoleInputdanUpdateRoleInput


@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;
}

Jawaban

digita1-anal0g Oct 07 2020 at 04:08

Inti dari apa yang perlu Anda lakukan adalah menentukan addRolesbidang pada jenis Mutasi di skema Anda. Sebagai contoh

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!]
  }
`;

Kemudian tentukan addRolesresolver Anda dan panggil API yang sesuai.

JunmingWang Oct 09 2020 at 02:01

Saya berhasil menemukan jawaban dengan coba-coba. Saya akan mempostingnya di sini jika seseorang memiliki masalah yang sama:

@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;
  }
...
}

Saya akan tetap membuka bounty jika ada jawaban yang lebih baik.