简体   繁体   中英

type-graphql : Can't figure out how to create a resolver in case a class extending another class

I have a FinalClass that extends a BasicClass, with 2 additional fields of 2 other Classes. Basic Class and the 2 other Classes are linked to typeOrm Entites and a foreignkey in each class enabled to join the data.

I want the final class to gather all data so that I can query all of them. But I don't know how to implement the resolver in a proper way, for example, a getAllFinal() which will go through all BasicClass reports and collect the 2 other data.

I tried to create a resolver getAllBasic() in BasicClass, FieldResolvers for each additional fields in the FinalClass ? But I'm wondering , how I call all that stuff in the getAllFinal() ?

@ObjectType()
export class FinalClass extends BasicClass{
  @Field(() => [AnotherClass2], { nullable: true })
  userAliases: AnotherClass2[];

  @Field(() => [AnotherClass3], { nullable: true })
  userIdentity: AnotherClass3[];
}

@ObjectType()
export class BasicClass {
  @Field(()=>ID!)
  bcPrimaryKey: string;
}

@ObjectType()
export class AnotherClass2 {
  @Field()
  ac2PrimaryKey: string;
  @Field()
  bcPrimaryKey : string;
  @Field()
  value : number
}


@ObjectType()
export class AnotherClass3 {
  @Field()
  ac3PrimaryKey: string;
  @Field()
  bcPrimaryKey : string;
  @Field()
  thevalue : number
  @Field()
  thevalue2 : boolean
}

the below resolver is working fine, but this is not a clean way to do it I guess, because I'm calling the DB for each field:

@Resolver(FinalClass )
export class FinalClassResolver {
  @Query(() => [FinalClass ], { nullable: true })
  async getAllFinal(
    @Ctx() context: GlobalContext
  ): Promise<Array<Promise<FinalClass >>> {
    const features: BasicClass[] = await context.dbConnection
      .getRepository<BasicClass>("BasicClass")
      .createQueryBuilder("features")
      .skip(0)
      .take(1000)
      .getMany();

    const resu = features.map(async (user: BasicClass) => {
      const aliases: AnotherClass2[] = await context.dbConnection
        .getRepository<AnotherClass2 >("AnotherClass2 ")
        .createQueryBuilder("alias")
        .where("alias.bcPrimaryKey=:email", { email: user.bcPrimaryKey })
        .getMany();

      const identity: AnotherClass3[] = await context.dbConnection
        .getRepository<AnotherClass3>("AnotherClass3")
        .createQueryBuilder("identity")
        .where("identity.bcPrimarykey=:email", { email: user.bcPrimaryKey})
        .getMany();

      const item: BasicClass= {
        ...user,
        userAliases: aliases,
        userIdentity: identity
      };
      return item;
    });
    return resu;
  }

getAllFinal query should just return the list of base fields of FinalClass . Then you should create field resolvers userAliases and userIdentity of FinalClass that will resolve the relation between FinalClass and AnotherClass2 / AnotherClass3 .

That's the architecture of GraphQL resolvers. It's not super-optimal (3 queries) but with a dataloader it's much more optimized than REST when client perform 20 HTTP calls.

Finally came up with a cleaner way by creating a resolver in BaseClass, extending it in the FinalClassResolver and adding the missing fieldResolvers in the FinalClassResolver

@Resolver(BasicClass)
export class BasicClassResolver {
  @Query(() => [BasicClass], { nullable: true })
  async getBasicClassItems(
    @Ctx() context: GlobalContext
  ): Promise<BasicClass[]> {
    const items: BasicClass[] = await context.dbConnection
      .getRepository<BasicClass>("BasicClass")
      .createQueryBuilder("items")
      .skip(0)
      .limit(1000)
      .getMany();

    return items;
  }
}


@Resolver(FinalClass)
export class FinalClassResolver extends BasicClassResolver {
  @Query(() => [FinalClass], { nullable: true })
  async getAllFinalItems (@Ctx() context: GlobalContext) {
    return this.getBasicClassItems(context);
  }

  @FieldResolver()
  async userAliases(
    @Root() item: BasicClass,
    @Ctx() context: GlobalContext
  ): Promise<AnotherClass2[]> {
    const aliases: AnotherClass2[] = await context.dbConnection
      .getRepository<AnotherClass2>("AnotherClass2")
      .createQueryBuilder("alias")
      .where("alias.itemId=:itemId", { itemId: item.Id })
      .getMany();

    return aliases;
  }

  @FieldResolver()
  async userIdentity(
    @Root() item: BasicClass,
    @Ctx() context: GlobalContext
  ): Promise<AnotherClass3[]> {
    const identity: AnotherClass3[] = await context.dbConnection
      .getRepository<AnotherClass3>("AnotherClass3")
      .createQueryBuilder("identity")
      .where("identity.itemId=:itemId", { itemId: item.id})
      .getMany();

    return identity;
  }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM