Set.paginate()
Get a page of paginated results using an
after
cursor.
Signature
Set.paginate((cursor: String, size: Number) => { data: Array<Any>, after: String | Null })
Description
Gets a page of paginated results using an
after
cursor.
The default page size of 16 can be changed using the
set.paginate()
or set.pageSize()
method, in the range
1 to 16000 (inclusive).
The cursor is stable in the sense that pagination through a Set is done for a fixed snapshot time, giving you a view of your data as it existed across the whole Set at the instant you started paginating. For example, given Set [a, b, c] when you start paginating, one item at a time, even if you delete item c after you started reading the Set, item c is returned.
The exception is if the history is no longer available for the deleted item
because history_days
is set to the default value of 0
or is less than the
minimum valid time needed. In that case, the deleted item is not returned with
the paginated results and an error is returned:
Requested timestamp <time> less than minimum allowed timestamp.
.
A cursor is valid for history_days
plus 15 minutes.
Invalid cursor
If you pass an invalid or expired after
cursor to
Set.paginate()
, the Fauna
Core HTTP API’s
Query endpoint
returns a query runtime error with an invalid_cursor
error code and a 400 HTTP status
code:
{
"error": {
"code": "invalid_cursor",
"message": "Cursor cursor is invalid or expired."
},
...
}
Fauna’s client drivers include classes for query runtime errors:
-
JavaScript driver:
QueryRuntimeError
-
Python driver:
QueryRuntimeError
-
Go driver:
ErrQueryRuntime ¶
-
.NET/C# driver:
QueryRuntimeException
-
JVM driver:
QueryRuntimeException
Return value
Type | Description | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
An object with:
|
Examples
Basic example
-
The page includes a pagination cursor:
Product.all().pageSize(2) { name }
{ data: [ { name: "cups" }, { name: "donkey pinata" } ], after: "hdWC1Y..." }
-
Use the cursor to access the next page:
Set.paginate("hdWC1Y...")
{ data: [ { name: "pizza" }, { name: "avocados" } ], after: "hdWC1Y..." }
Paginate in reverse
Paginated queries don’t include a before
cursor. Instead, you can use a range
search and document IDs or other unique field values to paginate in reverse. For
example:
-
Run an initial paginated query:
Product.all().pageSize(2)
{ data: [ { id: "111", coll: Product, ts: Time("2099-08-16T14:00:59.075Z"), name: "cups", description: "Translucent 9 Oz, 100 ct", price: 698, stock: 100, category: Category("123") }, { id: "222", coll: Product, ts: Time("2099-08-16T14:00:59.075Z"), name: "donkey pinata", description: "Original Classic Donkey Pinata", price: 2499, stock: 50, category: Category("123") } ], after: "hdW..." }
-
Page forward until you find the document you want to start reversing from:
Set.paginate("hdW...")
Copy the ID of the document:
{ data: [ { id: "333", coll: Product, ts: Time("2099-08-16T14:00:59.075Z"), name: "pizza", description: "Frozen Cheese", price: 499, stock: 100, category: Category("456") }, { // Begin reverse pagination from this doc ID. id: "444", coll: Product, ts: Time("2099-08-16T14:00:59.075Z"), name: "avocados", description: "Conventional Hass, 4ct bag", price: 399, stock: 1000, category: Category("789") } ], after: "hdW..." }
-
To reverse paginate, run the original query with:
-
A range search with a
to
argument containing the previous document ID. -
set.reverse()
: Append this to the query. -
set.pageSize()
: If used, place it afterset.reverse()
.
// "444" is the ID of the document to reverse from. Product.all({ to: "444" }).reverse().pageSize(2)
{ data: [ { // The results of the previous query are reversed. id: "444", coll: Product, ts: Time("2099-08-16T14:00:59.075Z"), name: "avocados", description: "Conventional Hass, 4ct bag", price: 399, stock: 1000, category: Category("789") }, { id: "333", coll: Product, ts: Time("2099-08-16T14:00:59.075Z"), name: "pizza", description: "Frozen Cheese", price: 499, stock: 100, category: Category("456") } ], after: "hdW..." }
To get historical snapshots of documents at the time of the original query, use an
at
expression:// Time of the original query. let originalQueryTime = Time.fromString("2099-08-16T14:30:00.000Z") at (originalQueryTime) { // "444" is the ID of the document to reverse from. Product.all({ to: "444" }).reverse().pageSize(2) }
-
-
Repeat the previous step to continue paginating in reverse:
Product.all({ to: "333" }).reverse().pageSize(2)
Traverse Set references
Sets are not persistable. You can’t store a Set as a field value or create a field definition that accepts a Set.
Instead, you can use a computed field to define a read-only function that dynamically fetches a Set:
collection Customer {
...
// Computed field definition for the `orders` field.
// `orders` contains a reference to a Set of `Order` collection documents.
// The value is computed using the `Order` collection's
// `byCustomer()` index to get the customer's orders.
compute orders: Set<Order> = ( customer => Order.byCustomer(customer))
...
}
If the field isn’t projected, it contains an
after
pagination cursor that
references the Set:
// Get a `Customer` document.
Customer.byEmail("alice.appleseed@example.com").first()
{
id: "111",
coll: Customer,
ts: Time("2099-10-22T21:56:31.260Z"),
cart: Order("412483941752112205"),
// `orders` contains an `after` cursor that
// references the Set of `Order` documents.
orders: "hdW...",
name: "Alice Appleseed",
email: "alice.appleseed@example.com",
address: {
street: "87856 Mendota Court",
city: "Washington",
state: "DC",
postalCode: "20220",
country: "US"
}
}
To materialize the Set, project the computed field:
let customer = Customer
.where(.email == "alice.appleseed@example.com")
.first()
// Project the `name`, `email`, and `orders` fields.
customer {
name,
email,
orders
}
{
name: "Alice Appleseed",
email: "alice.appleseed@example.com",
orders: {
data: [
{
id: "412483941752112205",
coll: Order,
ts: Time("2099-10-22T21:56:31.260Z"),
items: "hdW...",
total: 5392,
status: "cart",
customer: Customer("111"),
createdAt: Time("2099-10-22T21:56:31.104083Z"),
payment: {}
},
...
]
}
}
Alternatively, you can pass the after
cursor to
Set.paginate()
:
Set.paginate("hdW...", 2)
{
// Returns a materialized Set of `Order` documents.
data: [
{
id: "412483941752112205",
coll: Order,
ts: Time("2099-10-22T21:56:31.260Z"),
items: "hdW...",
total: 5392,
status: "cart",
customer: Customer("111"),
createdAt: Time("2099-10-22T21:56:31.104083Z"),
payment: {}
},
...
]
}
Is this article helpful?
Tell Fauna how the article can be improved:
Visit Fauna's forums
or email docs@fauna.com
Thank you for your feedback!