1
votes

I'm setting up a NestJS service using GraphQL to be the middleman between the UI and multiple other services. For the sake of this example, I need to display a list of books with their relevant information from a single publisher.

The UI will hit the nest service with an id of a publisher. I need to then call a service and get a list of book Ids. When I have the list of Ids I need to hit two separate services, each return a list of objects for each book id. I then need to build a list of book objects from both datasets.

An example of the book models is:

export class BookModel {

  @Field(type => BookInformationModel)
  bookInfo: BookInformationModel;

  @Field(type => BookSalesModel)
  bookSales: BookSalesModel;

}

An example of the flow is:

  1. UI hits Nest service with a publisher Id "pub1"
  2. Nest service goes to the publisher-service which returns a list of books linked to the publisher ['book1', 'book2']
  3. Nest service then hits the book-info-service that returns [{id: 'book1' title: ...}, {id: 'book2' title: ...}]
  4. Nest service then hits the book-sales-service that returns [{price: 123 currency: ...}, {price: 456 currency: ...}]
  5. Map both data sets to a list of BookModel
[{
  bookInfo: {id: 'book1' title: ...}
  bookSales: {price: 123 currency: ...}
}, {
  bookInfo: {id: 'book2' title: ...}
  bookSales: {price: 456 currency: ...}
}]

This is a simplified version of the resolver where I'm having trouble:

@Query(returns => [BookModel])
async getBooksByPublisherId(
  @Args('id', { type: () => String }) id: string
) {
  this.publisherService.getBookIds(id)
    .then(response => {
      return response.data;
    })
}

@ResolveField('bookInfo', returns => BookInformationModel)
async getBookInfo() {
  return this.bookInfoService.getBookInfo(bookIds)
}

@ResolveField('bookSales', returns => BookSalesModel)
async getBookSalesInfo() {
  return this.bookSalesService.getSalesInfo(bookIds)
}

There are two issues I'm having:

  1. How do I share the list of book Ids with the field resolvers?
  2. I'm not sure how I write the field resolvers for bookInfo, bookSales as the services return a list of objects.
1

1 Answers

3
votes

Figured it out. I needed to have the bookId on the BookModel. That way the field resolvers can access it via @Parent.

export class BookModel {

  @Field()
  bookId: string;

  @Field(type => BookInformationModel)
  bookInfo: BookInformationModel;

}
@Query(returns => [BookModel])
async getBooksByPublisherId(
  @Args('id', { type: () => String }) id: string
) {
  this.publisherService.getBookIds(id)
    .then(response => {
      return response.data.map(bookID => ({ bookId }));
    })
}

@ResolveField('bookInfo', returns => BookInformationModel)
async getBookInfo(
  @Parent() bookModel: BookModel
) {
  return this.bookInfoService.getBookInfo(bookModel.bookId)
}