Pagination
Introduction
Tezgraph uses the Relay Cursor Connections Specification for pagination. This means that all queries have the following structure.
connection {
edges {
cursor
node {
...
}
}
}
Inside the connection
(operations query), we have an edges
sub-selection. Edges consist of two queryable fields, cursor
and node
.
The node
field is a sub-selection in which we request the operation fields of interest.
Each node will be assigned a cursor. This cursor value can be used for the before
/after
query arguments.
Every Tezgraph query accepts the following arguments (as long as they are applicable to the results):
{
before: cursor | null;
after: cursor | null;
first: number | null;
last: number | null;
}
Using the first
/last
arguments and the before
/after
arguments, you can paginate through the results.
In the following image, the letters (A, B, C, D, E, F, G, H) will represent records and their cursors.
To get A, B, and C, we use the arguments first: 3
.
To get D, E, and F, we use the arguments first: 3
together with after: "C"
.
To get A, B, and C, we could also use the arguments last: 3
together with before: "D"
.
To get D, E, and F, we could also use the arguments last: 3
together with before: "G"
.
Tezgraph Query Examples
In this query, we request the first 3 account addresses available, their row cursors, and the page_info
fields.
Here is an example of what a page_info
response may look like.
"page_info": {
"has_next_page": true,
"has_previous_page": false,
"start_cursor": "KT18amZmM5W7qDWVt2pH6uj7sCEd3kbzLrHT",
"end_cursor": "KT18aoVDpcJ4E8kPJLYza6pQ82u4mfNfnhRa"
},
This specific page_info
response object tells how we may paginate through the available data. This object tells us:
"start_cursor": "KT18amZmM5W7qDWVt2pH6uj7sCEd3kbzLrHT"
- This is the cursor of the first record in the Tezgraph results."end_cursor": "KT18aoVDpcJ4E8kPJLYza6pQ82u4mfNfnhRa"
- This is the cursor of the last record in the Tezgraph results."has_next_page": true
- This value is true when there are additional retrievable records after (next page) the last record in the returned results. To get this to this next page of results, use theafter
argument, and pass it thepage_info.end_cursor
value.first: 3
after: "KT18aoVDpcJ4E8kPJLYza6pQ82u4mfNfnhRa"
"has_previous_page": false
- This value is true when there are additional retrievable records before (previous page) the first record in the returned results. To get this to this previous page of results, use thebefore
argument and pass it thepage_info.start_cursor
value.
In this query, we are requesting the next page of the results returned in the example above.
Limitations
You might wonder why TezGraph does not simply accept an offset
argument that lets you paginate through data?
- Offset-based pagination is not efficient to implement at the database level
- Offset-based pagination can miss some items (or duplicate them) in case data changes between different calls. For instance, if you query the last 3 operations and before you query the next 3, this account performs a new operation, one row will be duplicated in the two pages.
On the other hand, cursor
based pagination has its own limitations:
- You cannot "jump" ahead a specific number of pages and go directly to a certain location. You need the
cursor
value. - In case the data changes so that your cursor is not found in the database anymore, you have to go back to a cursor that still exists. In the context of Tezos blockchain, this can happen in the case of re-orgs.