entrest

Pagination

Explanation

How list pagination works in entrest — query parameters, response envelope, and when to disable it. For codegen defaults, see Codegen Configuration — Pagination.

What is Pagination?

entrest supports pagination for all list operations by default. Pagination at a high-level ensures that as the data returned by your API grows, there is a linear request size and query time/complexity, and you can better enforce rate limits for querying your API. If you cannot be confident that the number of results will not grow beyond a reasonable size, you should keep pagination enabled for any schemas where that may apply.

Configuration

Pagination has a few configuration options in a few locations:

Example of querying a paginated endpoint

Using our example API, and some of the example queries, we have the /users/{id}/pets endpoint which returns a list of pets associated with the user. Since the user could have many pets (who knows, maybe they run a cat cafe), this is a perfect use case for pagination.

curl --request GET \
  --url 'http://localhost:8080/users/4294967297/pets?pretty=true&page=1&per_page=5'
{
    "page": 1,
    "total_count": 124,
    "last_page": 25,
    "is_last_page": false,
    "content": [
        {
            "id": 1,
            "name": "Riley",
            "age": 1,
            "type": "DOG",
            "edges": {
                "owner": {
                    "id": 4294967297,
                    "username": "lrstanley",
                    "display_name": "Liam Stanley",
                    "email": "lrstanley@example.com",
                    "edges": {}
                }
            }
        },
        {
            "id": 2,
            "name": "Orea",
            "age": 2,
            "type": "DOG",
            "edges": {
                "owner": {
                    "id": 4294967297,
                    "username": "lrstanley",
                    "display_name": "Liam Stanley",
                    "email": "lrstanley@example.com",
                    "edges": {}
                }
            }
        },
        {
            "id": 3,
            "name": "Prince",
            "age": 9,
            "type": "CAT",
            "edges": {
                "owner": {
                    "id": 4294967297,
                    "username": "lrstanley",
                    "display_name": "Liam Stanley",
                    "email": "lrstanley@example.com",
                    "edges": {}
                }
            }
        },
        {
            "id": 4,
            "name": "Rex",
            "age": 2,
            "type": "DOG",
            "edges": {
                "owner": {
                    "id": 4294967297,
                    "username": "lrstanley",
                    "display_name": "Liam Stanley",
                    "email": "lrstanley@example.com",
                    "edges": {}
                }
            }
        },
        {
            "id": 5,
            "name": "Lucky",
            "age": 4,
            "type": "DOG",
            "edges": {
                "owner": {
                    "id": 4294967297,
                    "username": "lrstanley",
                    "display_name": "Liam Stanley",
                    "email": "lrstanley@example.com",
                    "edges": {}
                }
            }
        }
    ]
}

You will notice that we provided the page parameter (not required for the first page), and the per_page parameter (to control how many results we want per page). per_page will be limited to the MinItemsPerPage and MaxItemsPerPage values, and they have relatively sane defaults.

As we only requested 5 results, and there are a total of 124 results as shown in the total_count field, we can see that there are 25 pages in total. You can use the last_page or is_last_page fields to determine if we are on the last page, or if there are more pages to fetch.

Python example

Below is an example of how you might achieve collecting all results from a paginated endpoint in Python:


page = 1
results = []

while True:
    print(f"fetching page {page}...")
    resp = requests.get(f"http://localhost:8080/users/4294967297/pets?page={page}&per_page=100")
    data = resp.json()

    results += data["content"]

    if data["is_last_page"]:
        break

    page += 1

print(results)

Go example

Below is an example of how you might achieve collecting all results from a paginated endpoint in Go:

package main

    "encoding/json/v2"
    "fmt"
    "net/http"
)

type Pet struct {
    ID   int    `json:"id"`
    Name string `json:"name"`
    Age  int    `json:"age"`
    Type string `json:"type"`

    // [...]
}

// Recommend a generic type wrapper, since you'd likely have multiple endpoints which re-use the same
// base paginated structure.
type Paged[T any] struct {
    Page       int  `json:"page"`
    TotalCount int  `json:"total_count"`
    LastPage   int  `json:"last_page"`
    IsLastPage bool `json:"is_last_page"`
    Content    []*T `json:"content"`
}

func main() {
    page := 1
    var pets []*Pet
    var pageResults Paged[Pet]

    for {
        resp, err := http.Get(fmt.Sprintf("http://localhost:8080/users/4294967297/pets?page=%d&per_page=100", page))
        if err != nil {
            panic(err)
        }

        err = json.UnmarshalRead(resp.Body, &pageResults)
        if err != nil {
            panic(err)
        }
        resp.Body.Close()

        pets = append(pets, pageResults.Content...)

        if pageResults.IsLastPage {
            break
        }
        page += 1
    }

    fmt.Printf("total pets: %d\n", len(pets))
}

Last updated on

On this page