Gbolahan Olagunju passionate about all things javascript.

Pagination in GraphQL with Prisma the right way

2 min read 652

GraphQL

When working with a database that has millions of records, it’s very useful to adopt pagination since it helps us retrieve a subset of the data that we otherwise wouldn’t be able to access without querying every record on the table.

It can very expensive to retrieve this information from our database and it can have a huge impact on performance. It can also be expensive to render on the client side.

As of this writing, the default amount of records retrieved by Prisma on a table is 1,000 records — that is, if a subset of the record isn’t requested.

When querying a list of records, we can fetch certain parts (i.e. pages) of that list by supplying pagination arguments.

There are 5 major arguments we can use for pagination in Prisma: first, last, after, before, and skip.

In this article, we’ll be looking at various ways we can combine these arguments to effectively paginate our data.

We’ll also be using this public API for sample demonstrations.

Using first or last with skip

Imagine an app that has pagination implemented with buttons as indicated below and has a page size of 10 items.

To get this to work, we would need to rewrite our typedef definition to accept arguments and also implement it in the resolver function for that query.

We won’t be doing that, seeing as how we are using an already-built public API. Looking at the documentation for this shows that the query has been defined to accept those arguments.

Okay, let’s get our feet wet.

  • If we visit the public API, we’ll see the doc section.
  • Clicking the doc section, we’ll see the query, mutation, and subscription.
  • Then we’ll click on the query type to see all the queries that are available to us.

For the purposes of this article, we will be using the allStarships query.

     {
        allStarships(first: 10) {
          id
          name
          length
          manufacturer
        }
      }

When we ran this code, a total of 10 records were returned. However, this isn’t complete for pagination because the same set of 10 records will be returned every time.

To ensure it works properly, we need to introduce another argument called skip.

Here’s how:

{
    allStarships(first: 10, skip: 10) {
      id
      name
      length
      manufacturer
    }
  }

This gives us the second page, or the next 10 records. This can be done dynamically by sending the page number from the buttons multiplied by our page size.

We can get the first, second, and third page like this:

//first page
 // number to skip pageNumber = 1
number = 10 * (1 - 1); // 0
...
allStarships(first: 10, skip: 0) 
//second page 
//number = 10 * (2 - 1); // 10
allStarships(first: 10, skip: 10) 
// third page 
//number = 10 * (2 - 1); // 10
allStarships(first: 10, skip: 20)

Pagination

We could also use the last argument, but we would be querying the table (collection if mongoDB was the database of choice) from the last record entered rather than the above, which queries from the top of the table.

Using before or after with skip

Imagine we have the navigation of a page implemented such that when you get to the bottom of the page, you can use the last id to fetch more records after it.

 

load more posts

In our example, we can decide to fetch 10 more records.

Here’s how it’ll look in code:

{
    allStarships(first: 10, skip: 10) {
      id
      name
      length
      manufacturer
    }
  }

This gets us 10 records after the specified id . We can also use last with before to get records before the specified id.

Note: We can’t combine the use of first with before, or last with after.

If we do that in a query, the first or last is what will be applied (at either the end or the beginning of the list, depending on which is being used) while the before or after argument is simply ignored.

Conclusion

It’s important to apply pagination when querying records from our database because it helps to optimize the performance of our servers. It also helps to curb expensive renders at the client level.

200’s only : Monitor failed and slow GraphQL requests in production

While GraphQL has some features for debugging requests and responses, making sure GraphQL reliably serves resources to your production app is where things get tougher. If you’re interested in ensuring network requests to the backend or third party services are successful, try LogRocket.https://logrocket.com/signup/

LogRocket is like a DVR for web apps, recording literally everything that happens on your site. Instead of guessing why problems happen, you can aggregate and report on problematic GraphQL requests to quickly understand the root cause. In addition, you can track Apollo client state and inspect GraphQL queries' key-value pairs.

LogRocket instruments your app to record baseline performance timings such as page load time, time to first byte, slow network requests, and also logs Redux, NgRx, and Vuex actions/state. .
Gbolahan Olagunju passionate about all things javascript.

Leave a Reply