‫Now, another extremely important feature
‫of a good API is to provide pagination.
‫So basically allowing the user
‫to only select a certain page of our results,
‫in case we have a lot of results.
‫So let's pretend that we have, for example,
‫1000 documents in a certain collection.
‫And we say that on each page we have 100 documents.
‫So that would mean that we'd have 10 pages, right?
‫So 10 times 100 is 1000.
‫And so based on that, how are we gonna implement pagination
‫using or query string?
‫Well, we will use the page and delimit fields.
‫So there will be a page field.
‫Let's say we want page two
‫and there will be a limit field.
‫And this limit here basically means the amount
‫of results that we want per page.
‫And that's actually setted here only to 10
‫and of course we have to correct this one here.
‫It's not a comma, but an and.
‫So page two and the limit 10.
‫Now going back to the example of 1000 results,
‫if the limit is 10, so only 10 results per page,
‫well then we're gonna have 100 pages
‫and in here we are then displaying page number 2
‫of these 100 pages.
‫Okay?
‫Now, we need now a way of implementing this using Mongoose.
‫So let's take a look at how we could do that
‫by going back to our code.
‫So feature number four,
‫Pagination.
‫All right,
‫And I will start by building an example query here
‫just like we did before.
‫So let's say that the query is equal query.
‫And now what kind of methods do we have
‫in order to implement pagination?
‫Well, the most useful one is skip
‫and I'm gonna explain what it does in a second,
‫so let's just put a random number here.
‫So skip and limit,
‫and let's put 10.
‫and so this limit here is actually exactly the same
‫as the limit that we defined in the query string.
‫So basically the amount of results
‫that we want in the query.
‫And then skip, that we have here, is the amount of results
‫that should be skipped before actually querying data.
‫All right, so again, this is just a placeholder here.
‫Let's go back to this example that we have here.
‫I'm just gonna copy this query string here.
‫so let's say that the user wants page number two
‫with 10 results per page.
‫That means that results one to 10 are on page one,
‫and 11 to 20 are on page 2.
‫Okay, and so what that means is that we want to skip
‫10 results before we actually start querying.
‫Okay.
‫So again, one to 10
‫are for page one
‫and then 11 to 20
‫are for page two,
‫and so on and so forth.
‫So 21 to 30 will be page three,
‫And so on and so forth.
‫And so we need to skip 10 results
‫in order to get to result number 11, right?
‫So to result number 11 which will the first one on page two.
‫Okay, and since it is page two that was requested,
‫well, again we need to skip 10 results
‫before we actually start page two.
‫Okay? Make sense?
‫And for example, if we requested page number three,
‫well then of course, 20 results would
‫first have to be skipped.
‫And so we will need some way
‫of calculating this skip value here.
‫So based basically on the page and the limit.
‫Now you might ask why I do not directly ask for the
‫skip value in the query string,
‫but that's because for the user this value here is
‫kind of abstract, okay?
‫It's way easier to simply say, "Well I want page number one,
‫"or I want page number five
‫"or I want like page number 10."
‫Okay, so for the user it's much easier
‫to not deal with skip values here
‫and all that stuff, the user wants to have it easy
‫and to just define a page.
‫Now before we can actually get started
‫calculating the skip value, we need to first get the page
‫and the limit from the query string
‫and we should also define some default values.
‫Okay, so that's basically
‫because we still want to have pagination
‫even if the user does not specify any page
‫or any limit.
‫Because for example let's say that we have a million results
‫in our database,
‫and then of course when the user does the request
‫we would not simply show all of these 10 million results.
‫That wouldn't be very user friendly, would it?
‫And so, I will define by default page number one
‫and a limit of let's say 100.
‫So that by default when a user requests all of the tours
‫in this example, then he only gets 100,
‫and not a million, all right?
‫So the page is of course request.query.page
‫and I'm now going to multiply it by one
‫which is just a nice trick to convert
‫a string to a number.
‫Okay, so maybe you noticed before that each time that we
‫actually put a number in a query string,
‫it will then be a string or a query object,
‫and so we need to fix that simply by multiplying by one.
‫Okay, and then by default, we want page number one.
‫All right?
‫And so this is a nice way in JavaScript
‫of basically defining default values.
‫And I'm sure you're familiar with that, right?
‫Anyway, the limit is on req.query.limit
‫times one again to convert it,
‫or the default of 100 that we just mentioned.
‫So ideally the user will only specify the page number
‫that he requests
‫and to not even bother with the page limit.
‫That's for more specific use cases.
‫Okay, and now all we need to do is to then define
‫so to calculate basically
‫that skip value that we just talked about here before.
‫And the best way of doing that is to go back to an example.
‫So again, let's say we are requesting page number three,
‫with the limit of 10.
‫and we see here for page number three the results are
‫from 21 to 30.
‫So it starts at result number 21, meaning that we need to
‫skip 20 results.
‫And 20 results is basically two times 10,
‫so two times this limit.
‫Okay, and from there we actually start getting a formula.
‫So two times ten is basically three minus one times 10.
‫And three is the page that we're on.
‫So that is our formula.
‫So page minus one
‫and so the previous page, basically,
‫times
‫the limit.
‫Okay, so I hope that made sense,
‫let's now replace these values here.
‫Skip
‫and limit of limit.
‫Okay?
‫So basically, this number here is all the results that
‫come before the page that we're actually requesting now.
‫So again, if we are requesting page number three
‫our results are gonna start at page number 21.
‫And so we wanna skip 20 results before that.
‫And so 20 results is
‫because we have 2 pages time 10 results on each,
‫Yeah, it's gonna be the page that we just requested.
‫So page here, minus one,
‫so the previous page times the number of results
‫on each page.
‫Okay, so that's the amount of documents that
‫are gonna be skipped.
‫Okay, so I hope that made sense.
‫Let's now go ahead and actually try this.
‫And since we only have so few results here
‫we need to test it with a really small limit.
‫So let's say that we only want three results per page,
‫and let's actually start on page number one.
‫So send it, and indeed now we only get
‫three results as you can see here.
‫So these three, let's see.
‫So The Forest Hiker,
‫The Sea Explorer,
‫and The City Wanderer.
‫Okay?
‫Let's try page number two,
‫and for some reason the postman keeps jumping around
‫each time that I change the URL.
‫Anyway, now we have The Park Camper,
‫The Snow Adventurer,
‫and The Sports Lover.
‫So you start seeing that we actually
‫now have different tours.
‫Okay?
‫And so we can kind of say that
‫our pagination here is already working.
‫Now the last page,
‫and we have now The Northern Lights,
‫The Wine Taster,
‫and The Star Gazer.
‫All right?
‫Now what if we try to go to page number four?
‫We already know that we only have nine tours,
‫and so on page number four there should be nothing.
‫Right?
‫So let's test that.
‫And indeed we get zero results.
‫But that is of course not ideal.
‫Okay, and so let's now go ahead and fix that
‫and basically kind of throw an error each time
‫the user selects a page that does not exist.
‫Because that's basically the situation here.
‫The user requested a page that simply does not exist.
‫We don't have enough results to have four pages
‫with three results.
‫Let's now do that,
‫and this will actually only happen
‫when there is a page on the query
‫and so let's actually create this if statement here.
‫So if request.query.page,
‫only in this case we will test if we are skipping more
‫tours than we actually have.
‫So let's get the amount of tours.
‫So number of tours is equal to,
‫and now we're actually going to learn a new method.
‫So a new method there is on the Tour model
‫which is called countDocuments.
‫Okay? And as the name says this is going to return
‫the number of documents, all right?
‫Actually it's gonna return a promise
‫but we then await the promise
‫and so it will then come back
‫with the result of the amount of tours.
‫Okay? And so if the number of documents that we skip
‫is greater than the number of documents that actually exists
‫well then that means that the page does not exist, alright?
‫That make sense?
‫So if skip is greater
‫than the number of tours,
‫and for now what I'm gonna do here is to throw a new error.
‫Okay?
‫So throw new error
‫this page does not exist.
‫Now why am I throwing an error here?
‫Well, simply because if I throw an error here
‫in the triblock which we are currently in,
‫it will then automatically
‫and immediately move on to the catch block,
‫and it will then send back this 404 kind of fail message.
‫Okay?
‫And so that's what we want for now.
‫Just keep in mind that we will implement much better
‫error handling a bit later in the course.
‫And actually right in the next section, okay?
‫But for now let's just keep it simple,
‫throw this error here
‫in case that we're trying to skip more documents
‫than we actually have.
‫Okay?
‫So this is the right case, let's send it here
‫and that's not the result that I expected
‫so let's go back
‫so right now our page is four
‫and the limit is three.
‫So the skip here would be three time three, so nine, okay?
‫And the number of tours is nine as well
‫and so skip is not greater than the number of tours
‫and therefore we don't get this error.
‫So what we need to do is to set it to greater or equal.
‫Okay, and so that should now work.
‫And that takes a long time,
‫and it did.
‫Now we get the fail status here
‫and a 404.
‫For some reason
‫this error is not showing up here
‫which it actually should.
‫But don't worry about that, that's not really important.
‫What matters is that it did actually enter our catch block,
‫and then send back this 404 response.
‫Everything else we're gonna implement a bit later.
‫Okay, and that's actually it.
‫So that's all the methods that we're gonna add to our query,
‫and so when we finally reach the next line of code here,
‫our query will then be awaited,
‫and return with the tours.
‫Okay, and at this point our query might actually look
‫something like
‫so something like this, something like
‫well what do we have here
‫we have sort, select,
‫so we might have sort,
‫and then some select there
‫we have also
‫skip
‫we have limit as well,
‫and so that's really kind of a big query.
‫And again, what allows us to that that is
‫that each of these methods here will always return
‫a new query that we can then chain on the next method
‫and the next method,
‫and the next method until we finally await the query
‫so that it can actually give us our documents.
‫Okay, so let's get rid of all these comments
‫and yeah, that's it for now.
‫For these features we're just gonna add one more
‫in the next lecture,
‫but that one is gonna be a bit different than these.
‫It's not gonna use one of these query methods, all right?
‫So I hope that over the last couple of lectures
‫you really learned the ins and outs
‫of querying data with Mongoose.
‫So of course, all of these methods that we used are not
‫only useful for these features that we implemented here.
‫You can really create all kinds of querys
‫that you can imagine for all kinds of applications.
‫So I showed you all the techniques here in this context
‫of these different API features,
‫but of course you're gonna be able to use them
‫all over your applications in the future, okay?
‫So I hope that was fun for you
‫and if it was, then let's move on now right to the next one.
‫See you!