Skip to main content

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.

image info

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 the after argument, and pass it the page_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 the before argument and pass it the page_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?

  1. Offset-based pagination is not efficient to implement at the database level
  2. 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:

  1. You cannot "jump" ahead a specific number of pages and go directly to a certain location. You need the cursor value.
  2. 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.