It would be great if you could explain the underlying mechanism of this approach. What sets this apart from traditional pagination I have never worked with NoSQL. I assume that it's kind of index organized table. In the traditional method, - we start reading from the beginning - count to the offset - and then fetch records until we reach the page size With this new approach, we can use the index to directly jump to the starting point, improving performance. However, how does this work when we need to apply a filter and then skip and take records? Please explain clearly. Else, this video is not useful at all. We don't want to follow something just because an expert says to do it. We need to know the reason to think if it is worth implementing for our use case
The raison d'etre for continuation tokens is that they provide a stable api. Regardless of how your implementation of paging works, the state needed to make paging go is a) not stored anywhere on the backend, and b) opaque to the client. That means that however you might need to change that logic is fair game. Whether you find yourself moving to a different datastore, or aggregating results from multiple sources, or anything else, there's no state stored, and nobody can depend on that structure, so there is no breakage. You can also extend this idea of encoding server state in an opaque token to facilitate _any_ stepwise, stateful process, not just paging. At least any that play out in interactive time. Because again, the key enabling points are: a) no state is stored on the backend b) the state is opaque to the client
So @9:30 you mention you might want to hash to continuation token so as not to expose internal id's. But I can't go back from the hash to the actual id unless I keep a list on the server. Also in the example you use an order integer Id, but what when I want to page through a filtered set of results that messed with this integer or any orderer key values. The way back is even harder. Let's assume SQL. Continuation could be just Id > continuationToken, but going back you would need to do Id< continuationToken and add an order by on the Id column with of course a limit/top restriction. This also ties what you can select to the Id order field. The less efficient Skip/Take query can easily manage forward and backward paging, and still works when you have filtering involved, or even ordering on a specific value. That generic solution might be less efficient but it makes working with pagination a lot easier.
The token just encodes the next step. You can provide a forward token, a back token, or tokens that jump to particular places. I usually provide a forward and back token in each page result. The point is that it holds _all of the pagination state needed for the backend to produce the next step_ and that it is _opaque to the client_. If you observe those two things, then you can change any pagination logic and your api remains stable.
Pagination sucks when, during someone or some process paging your data, the data is modified. Let's say you're paging employees and you've just gone from page one to page two. Meanwhile, while you were looking at page one, an employee was added on the first page. Now you've "missed" the first employee and on page two you're seeing the last employee of page one as first entry. These 'continuation tokens' don't solve that either. Also, for every API request you're sorting the entire thing only to determine which records go on which page and to then only return a fraction of the data. And then the user / process asks for the next/prvious/other page and it all needs to be done all over again. It's horrendously inefficient. Whenever you can, try to avoid paging.
Nah, I think continuation tokens are a good practice to avoid breaking changes to the api, not for any implementation reason. They just make the pagination state opaque to the client so that it can evolve. Moving to a non-relational store is just one of the options it makes available.
@@Novascrub Then it depends on the requirements, if one of the requirements is to allow users to jump into any page, and also alow them to select display size, then continuation tokens are not enough. Or you have to do a bit more that you would have if you didn't use them. Think of a view with a grid, which you can jump to any page and also have an option to select page size
this may be useful when you're building some feed (e.g: instagram), but definitely, when building some adult content website, where people need some more precise navigation
This is really nice explanation especially adding the notes at 5:12 which helped me giving a background why we need limit and offset.
Is this similar or equals to cursor pagination?
It would be great if you could explain the underlying mechanism of this approach. What sets this apart from traditional pagination
I have never worked with NoSQL. I assume that it's kind of index organized table. In the traditional method,
- we start reading from the beginning
- count to the offset
- and then fetch records until we reach the page size
With this new approach, we can use the index to directly jump to the starting point, improving performance. However, how does this work when we need to apply a filter and then skip and take records?
Please explain clearly. Else, this video is not useful at all. We don't want to follow something just because an expert says to do it. We need to know the reason to think if it is worth implementing for our use case
The raison d'etre for continuation tokens is that they provide a stable api. Regardless of how your implementation of paging works, the state needed to make paging go is a) not stored anywhere on the backend, and b) opaque to the client. That means that however you might need to change that logic is fair game. Whether you find yourself moving to a different datastore, or aggregating results from multiple sources, or anything else, there's no state stored, and nobody can depend on that structure, so there is no breakage.
You can also extend this idea of encoding server state in an opaque token to facilitate _any_ stepwise, stateful process, not just paging. At least any that play out in interactive time. Because again, the key enabling points are:
a) no state is stored on the backend
b) the state is opaque to the client
So @9:30 you mention you might want to hash to continuation token so as not to expose internal id's. But I can't go back from the hash to the actual id unless I keep a list on the server.
Also in the example you use an order integer Id, but what when I want to page through a filtered set of results that messed with this integer or any orderer key values.
The way back is even harder. Let's assume SQL. Continuation could be just Id > continuationToken, but going back you would need to do Id< continuationToken and add an order by on the Id column with of course a limit/top restriction. This also ties what you can select to the Id order field.
The less efficient Skip/Take query can easily manage forward and backward paging, and still works when you have filtering involved, or even ordering on a specific value. That generic solution might be less efficient but it makes working with pagination a lot easier.
What if I need to navigate between pages non sequentially? Aka: Page 1 -> Page 6
I think that cannot be done and if you need to change the page size in a grid that is also an issue with this approach
that's an excellent explanation and use case that all of us have faced at some point...
thanks Gui!
Is this technique a forward only process? Otherwise, you would have to keep track of the continuation tokens as you go along.
The token just encodes the next step. You can provide a forward token, a back token, or tokens that jump to particular places. I usually provide a forward and back token in each page result.
The point is that it holds _all of the pagination state needed for the backend to produce the next step_ and that it is _opaque to the client_. If you observe those two things, then you can change any pagination logic and your api remains stable.
Surely you'll still need to do a second query to get the total?
Pagination sucks when, during someone or some process paging your data, the data is modified. Let's say you're paging employees and you've just gone from page one to page two. Meanwhile, while you were looking at page one, an employee was added on the first page. Now you've "missed" the first employee and on page two you're seeing the last employee of page one as first entry. These 'continuation tokens' don't solve that either.
Also, for every API request you're sorting the entire thing only to determine which records go on which page and to then only return a fraction of the data. And then the user / process asks for the next/prvious/other page and it all needs to be done all over again. It's horrendously inefficient. Whenever you can, try to avoid paging.
So what is the alternative? Unbounded result sets? Also... paging and sorting over indexed columns is not that inefficient.
You Should Know This Before Using Page Numbers on Your API (with non-relational databases)
explain?
Nah, I think continuation tokens are a good practice to avoid breaking changes to the api, not for any implementation reason. They just make the pagination state opaque to the client so that it can evolve. Moving to a non-relational store is just one of the options it makes available.
@@Novascrub
Then it depends on the requirements, if one of the requirements is to allow users to jump into any page, and also alow them to select display size, then continuation tokens are not enough. Or you have to do a bit more that you would have if you didn't use them.
Think of a view with a grid, which you can jump to any page and also have an option to select page size
@@robertmrobo8954 I can do all that with tokens. Think about it for a second.
this may be useful when you're building some feed (e.g: instagram), but definitely, when building some adult content website, where people need some more precise navigation