Is there a way to do pagination on a child field of a GraphQL type?

Viewed 76

I am working on adding a pagination functionality for the server side of a GraphQL API. For context, I include a sample of the UML diagram of the Products table and its referenced tables from the database enter image description here

The graphQL schema and resolver are:

 const schema = gql`
  type Product {
    id: Int!
    events: [ProductEvent!]!
    orderRows: [OrderRow!]!
    ...
  }
  type ProductEvent {
    id: Int!
    product: Product!
    delta: Int!
    date: Date!
    ...
  }
  type OrderRow {
    id: Int!
    order: Order!
    product: Product!
    ...
  }
  type Order {
    id: Int!
    rows: [OrderRow!]!
    customer: Customer!
    shippingDate: Date!
    ...
  }

  const resolvers = {
  Product: {
    events: async (product: Product, _args: any, context: Context) => 
    context.loaders.loadProductEvents.load(product.id),
    orderRows: async (product: Product, _args: any, context: Context) => 
    context.loaders.loadOrderRows.load(product.id),
  },
  Query: {
    product: (_parent: any, { id }: { id: number }, context: Context) =>
      context.models.Product.findByPk(id),
    products: async (
      _parent: any,
      { onlyActive, producerId }: { onlyActive?: boolean; producerId?: number },
      context: Context,
    ) => {
      ...
    },
  }

The resolvers for Product.events and Product.orderRows call a DataLoader and returns all events and orderRows corresponding to the queried product.id param.

The problem is that one products can appears in a multiple events (e.g., purchase, loss, sampling) and order-rows. For that reason, I want to to add a pagination functionality for the Product.events and Product.orderRows when querying a product.id.

I have been trying to implement something like:

...
Query: {
    productPaginationByMonth: async(
      _parent: any, 
      { id, first, after }: { id: number; first: number; after?: Date },
      context: Context,
    ) => {
      function getOrderRowsWithinRange(productId: number, first: number, after: any){
        // query $first order-rows containing productId $after a certain shippingDate 
        ...
        // return [OrderRow]
      }
      function getEventsWithinRange(productId: number, first: number, after: any){
        // query $first product events containing productId $after a certain date
        ...
        // return [ProductEvent] 
      }
      ...
      // I'd like to return something like this
      return {...Product.findByPK(id), events: getEventsWithinRange(id, first, after), orderRows: getOrderRowsWithinRange(id, first, after)}
    },
  }

The spread operation doesn't work and I am now questioning if this approach is event possible. So question (1) is how to do pagination on the child fields of graphQL type?

Another question is about DataLoader. And question (2) is can I overload the Dataloader so that it returns an array of ProductEvents and OrderRows within a time range?

0 Answers
Related