Skip to content

Commit

Permalink
Merge pull request #206 from justin-tay/cursor_gh-pages
Browse files Browse the repository at this point in the history
Updates for cursor pagination
  • Loading branch information
aklish authored Sep 22, 2024
2 parents 748297d + 20687cc commit b77d87f
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 6 deletions.
70 changes: 65 additions & 5 deletions pages/guide/v7/10-jsonapi.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,13 +224,17 @@ Argument values must be URL encoded. There is no limit to the number of argumen
Elide supports:
1. Paginating a collection by row offset and limit.
2. Paginating a collection by page size and number of pages.
3. Returning the total size of a collection visible to the given user.
4. Returning a _meta_ block in the JSON-API response body containing metadata about the collection or individual resources.
5. A simple way to control:
3. Paginating a collection after or before a cursor.
4. Returning the total size of a collection visible to the given user.
5. Returning a _meta_ block in the JSON-API response body containing metadata about the collection or individual resources.
6. A simple way to control:
* the availability of metadata
* the number of records that can be paginated

### Syntax

#### Offset Pagination

Elide allows pagination of the primary collection being returned in the response via the _page_ query parameter.

The _rough_ BNF syntax for the _page_ query parameter is:
Expand All @@ -253,9 +257,52 @@ Legal combinations of the _page_ query params include:
1. offset & limit
1. offset & limit & totals

#### Cursor Pagination

Cursor pagination is not enabled for the models by default and needs to be enabled by using annotating the model with the `@Paginate` annotation.

```java
@Include
@Entity
@Paginate(modes = { PaginationMode.OFFSET, PaginationMode.CURSOR })
public class Book {
}
```

Cursor pagination is supported by the following data stores:
* Hashmap Data Store
* JPA Data Store

The JPA Data Store implements keyset pagination which assumes that appropriate indexes are created and that the sortable columns are non nullable.

The _rough_ BNF syntax for cursor pagination is:
```
<QUERY> ::=
"page" "[" "size" "]" "=" <INTEGER>
| "page" "[" "first" "]" "=" <INTEGER>
| "page" "[" "after" "]" "=" <STRING>
| "page" "[" "last" "]" "=" <INTEGER>
| "page" "[" "before" "]" "=" <STRING>
| "page" "[" "totals" "]"
```

Legal combinations of the cursor query params include:
1. first
1. last
1. after & size
1. before & size
1. first & totals
1. last & totals
1. after & size & totals
1. before & size & totals

Note that scrolling backwards using _last_ and _before_ does not change the sort order.

### Meta Block
Whenever a _page_ query parameter is specified, Elide will return a _meta_ block in the
JSON-API response that contains:

#### Offset Pagination

Whenever a _page_ query parameter is specified, Elide will return a _meta_ block in the JSON-API response that contains:
1. The page _number_
2. The page size or _limit_
3. The total number of pages (_totalPages_) in the collection
Expand All @@ -264,6 +311,19 @@ JSON-API response that contains:
The values for _totalPages_ and _totalRecords_ are only returned if the _page[totals]_
parameter was specified in the query.

#### Cursor Pagination

Whenever cursor pagination is used, Elide will return a _meta_ block in the JSON-API response that contains:
1. The cursor of the first record in the collection indicated by _startCursor_
2. The cursor of the last record in the collection indicated by _endCursor_
3. Whether there is a next page in _hasNextPage_
4. Whether there is a previous page in _hasPreviousPage_
5. The total number of records (_totalRecords_) in the collection.

The values for _totalRecords_ are only returned if the _page[totals]_ parameter was specified in the query.

The value for _hasNextPage_ or _hasPreviousPage_ may return false if it cannot be efficiently determined when scrolling in the opposite direction. For instance when scrolling backwards using _before_, _hasPreviousPage_ should indicate whether there are more records scrolling backwards but _hasNextPage_ may indicate false even if there are more records after the _endCursor_ if the data store cannot efficiently determine this.

### Example

Paginate the book collection starting at the 4th record. Include no more than 2 books per page.
Expand Down
61 changes: 60 additions & 1 deletion pages/guide/v7/11-graphql.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,11 +225,13 @@ or 'Science Fiction':
## Pagination
--------------------------

### Offset Pagination

Any relationship can be paginated by providing one or both of the following parameters:
1. **first** - The number of items to return per page.
2. **after** - The number of items to skip.

### Relationship Metadata
#### Relationship Metadata

Every relationship includes information about the collection (in addition to a list of edges)
that can be requested on demand:
Expand All @@ -252,6 +254,63 @@ These properties are contained within the _pageInfo_ structure:
}
```

### Cursor Pagination

Cursor pagination is not enabled for the models by default and needs to be enabled by using annotating the model with the `@Paginate` annotation.

```java
@Include
@Entity
@Paginate(modes = { PaginationMode.OFFSET, PaginationMode.CURSOR })
public class Book {
}
```

Cursor pagination is supported by the following data stores:
* Hashmap Data Store
* JPA Data Store

The JPA Data Store implements keyset pagination which assumes that appropriate indexes are created and that the sortable columns are non nullable.

Where cursor pagination is supported, any relationship can be paginated by providing one or both of the following parameters:

Scrolling forwards

1. **first** - The number of items to return per page starting from the start.
2. **after** - The cursor indicating the item the returned collection is after.

Scrolling backwards

1. **last** - The number of items to return per page starting from the end.
2. **before** - The cursor indicating the item the returned collection is before.

Note that scrolling backwards using _last_ and _before_ does not change the sort order.

#### Relationship Metadata

Every relationship includes information about the collection (in addition to a list of edges)
that can be requested on demand:

2. **startCursor** - The cursor indicating the first item in the current page.
1. **endCursor** - The cursor indicating the last item in the current page.
3. **hasPreviousPage** - Whether or not more items exist before the current page.
3. **hasNextPage** - Whether or not more items exist after the current page.
4. **totalRecords** - The total number of records in this relationship across all pages.

These properties are contained within the _pageInfo_ structure:

```
{
pageInfo {
startCursor
endCursor
hasPreviousPage
hasNextPage
totalRecords
}
}
```

## Sorting
--------------------------

Expand Down

0 comments on commit b77d87f

Please sign in to comment.