# 在 GraphQL API 中实现分页

了解如何使用 GraphQL API 中的基于游标的分页来遍历数据集。

## 关于分页

GitHub 的 GraphQL API 限制了可以在单个请求中提取的项数，以防止对 GitHub 服务器发出过多请求或滥用请求。 使用 GraphQL API 时，必须在任何连接上提供 `first` 或 `last` 参数。 这些参数的值必须介于 1 到 100 之间。 GraphQL API 将返回由 `first` 或 `last` 参数指定的连接数。

如果要访问的数据拥有的连接数大于 `first` 或 `last` 参数指定的项数，则响应将按指定大小分为较小的“页面”。 可以一次提取这些页面，直到检索到整个数据集为止。 每个页面都包含由 `first` 或 `last` 参数指定的项数，最后一页除外，最后一页包含的项数可能低于该值。

本指南演示如何在分页响应中请求其他结果页，如何更改每页返回的结果数，以及如何编写脚本来获取多页结果。

## 请求查询中的 `cursor`

使用 GraphQL API 时，可以使用游标来遍历分页后的数据集。 游标表示数据集中的特定位置。 可以通过查询 `pageInfo` 对象来获取页面上的第一个和最后一个光标。 例如：

```graphql
query($owner: String!, $name: String!) {
  repository(owner: $owner, name: $name) {
    pullRequests(first: 100, after: null) {
      nodes {
        createdAt
        number
        title
      }
      pageInfo {
        endCursor
        startCursor
        hasNextPage
        hasPreviousPage
      }
    }
  }
}
```

在此示例中，`pageInfo.startCursor` 提供了页面上第一项的游标。
`pageInfo.endCursor` 提供了页面上最后一项的游标。
`pageInfo.hasNextPage` 和 `pageInfo.hasPreviousPage` 指示在返回的页面之前和之后是否还存在页面。

## 更改每页显示的项数

`first` 和 `last` 参数用于控制返回的项数。 可以使用 `first` 或 `last` 参数提取的最大项数为 100。 如果查询涉及大量数据，则建议将请求的项数限制在 100 以下，以避免达到速率限制或节点限制。 有关详细信息，请参阅“[GraphQL API 的速率限制和查询限制](/zh/enterprise-server@3.22/graphql/overview/rate-limits-and-query-limits-for-the-graphql-api)”。

## 使用分页遍历数据集

返回查询的游标后，可以使用游标请求下一页的结果。 为此，您将使用 `after` 或 `before` 参数和游标。

例如，假设上例中 `pageInfo.endCursor` 的值为 `Y3Vyc29yOnYyOpHOUH8B7g==`，则可以使用以下查询请求下一页结果：

```graphql
query($owner: String!, $name: String!) {
  repository(owner: $owner, name: $name) {
    pullRequests(first: 1, after: "Y3Vyc29yOnYyOpHOUH8B7g==") {
      nodes {
        createdAt
        number
        title
      }
      pageInfo {
        endCursor
        hasNextPage
        hasPreviousPage
      }
    }
  }
}
```

可以继续发送响应中返回新 `pageInfo.endCursor` 值的查询，直到不再有要遍历的页面（通过 `pageInfo.hasNextPage` 返回 `false` 来指示）为止。

如果指定了 `last` 参数而不是 `first` 参数，则将首先返回结果的最后一页。 在这种情况下，你将使用 `pageInfo.startCursor` 值和 `before` 参数来获取上一页结果。
`pageInfo.hasPreviousPage` 返回 `false` 时，您已到达最后一页。 例如：

```graphql
query($owner: String!, $name: String!) {
  repository(owner: $owner, name: $name) {
    pullRequests(last: 1, before: "R3Vyc29yOnYyOpHOHcfoOg==") {
      nodes {
        createdAt
        number
        title
      }
      pageInfo {
        startCursor
        hasPreviousPage
      }
    }
  }
}
```

## 后续步骤

可以使用 GitHub 的 Octokit SDK 和 `octokit/plugin-paginate-graphql` 插件来支持在脚本中分页。 有关详细信息，请参阅 [plugin-paginate-graphql.js](https://github.com/octokit/plugin-paginate-graphql.js)。