Instructor: Another nice small feature
that we can add to an API is
to provide an alias route to a request
that might be very popular,
so it might be requested all the time.
And, for example, we might want
to provide a route specifically
for the five best cheap tours.
So, if we'd use our regular route here
with the filters and with all the features
that we already have,
the request would look a little bit like this.
So, let's get ride of all of this.
So, the five best and cheapest tours.
So, that means we have a limit of five
and then we're gonna sort by ratings and by price.
So, sort and then the average rating,
and descending, so minus ratings average.
And, in case they have the same average,
then we want the cheapest price possible.
And so, we're gonna sort also by price.
Let's quickly take a look at the results.
And, indeed, we get five tours here.
And, Postman does this scrolling again.
So, we have tours with 4.9,
4.9, 4.9 again,
4.8, and 4.7.
And so, these are actually our five best and cheapest tours.
If we said cheapest and best, well,
then maybe we would have to sort by price first
because some of them are not really cheap.
For example, this one.
But, we selected, first, the average.
And so, we sorted by the highest average first
and, only then in case of a tie, basically,
only then, by the price.
Now, let's say that this is a request
that is done all the time and we want
to provide a route that is simple
and easy to memorize for the user.
So, let's go to our app and try to implement that.
And, we're gonna start at their routes, so tour router.
And, we then need to create a new route.
And, let's do that here, right at the top.
So, router.route.
And so, how are we gonna call this route?
Well, let's say top-5-cheap.
So, quite a simple name, but it's gonna work.
And then, we actually only want
to get requests to this route.
And so, now it's time to think.
How are we gonna implement this functionality?
Well, in essence, what we want is
to actually still get all the tours just like here.
And so, let me go ahead and start by copying
and pasting that here.
So, we really still want to use this function here
because it doesn't really make sense
to rewrite all of the logic that is in there.
But, before we can call this route ender,
we basically want to prefill some of the fields
in the query string.
So, we already know
that our query string should look like this.
And, actually we can add some more stuff here.
But, in essence, our query string
has to look something like this.
And so, the solution is gonna be to run a middleware
before we actually run this getAllTours handler.
And so, that middleware function is then
gonna manipulate the query object that's coming in.
And so, this is yet another really nice example
of using middleware because you really need
to get familiar and used to this concept
of using middleware strategically in order
to change the request object as we need it.
So, let's add it here then.
So, tourController.
And then, the middleware function
that we're gonna create in a second,
which is gonna be called aliasTopTours.
So, let's copy that name, move to the tourController
and I'm gonna put it here at the very top.
So, exports.,
then request,
response,
and what's the third argument
that we need in the middleware, remember?
And, I know the Express section is kind of far away already
at this point, but I hope you remember
that the third argument here needs to be next.
So, in order to call the next middleware
that's in the middleware stack.
Give it a save.
And so, this error there should disappear.
And so, let's do what we said we would do.
So, basically to manipulate the query object
so that when it reaches the getAllTours handler,
it's then already different.
So, let's first do that and then really
take a look at what happens.
So, remember, the limit is gonna be set to five.
And, remember that everything is strings here
and so I'm setting this also to a string.
Now, what else did we had?
So, we have this sort, so let's just copy this here
and say req.query.sort.
It should be this.
And then, we can actually also specify some fields
so that the user doesn't get all of the fields
that we have in there.
So, let's say that we only want the name, the price,
the ratings average, the summary,
and the difficulty.
Give it a save and now all we need is next,
otherwise this middleware will be stuck here forever
and cannot move on.
So, let's now figure out a bit better
what's actually gonna happen here.
So, as soon as someone hits the top-5-cheap route,
we will start.
The first middleware that's gonna be run is aliasTopTours.
So, the function that we just created.
So, what this is gonna do is
that it will set these properties of the query object
to these values that we specified here.
Basically prefilling parts of the query object
before we then reach the getAllTours handler.
And so, as soon as we then get to this function,
the query object is already prefilled,
even if the user didn't put any
of these parameters in the query string.
And so, in essence,
what we're doing here is prefilling the query string
for the user so that the user doesn't have
to do it on his own.
And so, let's now actually go ahead and try this.
So, I'm copying this.
And, here it's not tours.
It is top-5-tours.
Whoa, what's going on here?
For some reason, it doesn't find this route,
so let's go back.
So, top-5-tours.
And so, here in the route, ah, okay.
It's called top-5-cheap,
so my mistake here.
So, cheap, send it now,
and that's still not correct.
Ah, yeah.
Of course, I still have to put the tours here, of course.
So, we are in the tours resource
and the whole router is mounted
onto this tours route, remember that.
And so, it's in that tours,
that kind of mini application, remember that,
where I created this top-5-cheap route.
So, let's hope it works now.
And, indeed, it does.
So, that worked, that's fantastic.
Now, of course, we could do a lot more alias routes here,
but that's not really necessary.
I really just wanted to show you the concept,
show you that it can be a nice feature
to add to any API and also I wanted to, again,
show you the power of middlewares.
So, we're talking about Mongoose here,
but still, it's very important to keep getting familiar
with the Express concepts that we talked about before.
Anyway, we're now done with our API features.
In the next video, we're just gonna quickly refactor all
of this to make the entire code a bit more modular
and, of course, better.