‫All right, and now just to finish this part,
‫let's create some factories for getting documents.
‫And let's start with getOne here, okay?
‫Exports.getOne, but this one is actually a bit trickier,
‫and that's because we have a populate
‫in the getTour handler.
‫So, let's take a look at that.
‫So, right here, in this one, we have this populate here,
‫which is different from all the other get handlers
‫in the other resources, right?
‫But, well, this is not really a problem
‫because we will simply allow ourselves to pass in
‫a populate options object into our getOne function, okay?
‫So, instead of simply passing in the model,
‫we will also have populate, so options, all right.
‫And so, from here we will then return
‫the normal handler function.
‫So, let's go ahead and again copy all of this,
‫all right.
‫So, we don't need this one here.
‫Then here, as always, it is model,
‫and here it is doc.
‫Well, actually here, document,
‫and here, once again, data equal to doc.
‫Now, we also need to make some changes here now
‫because of this populate,
‫so basically, we will first create the query,
‫and then, if there is the populate options object,
‫we will then add that to the query,
‫and then by the end, await that query, okay?
‫Make sense?
‫So, let's translate what I just said.
‫So, the query is simply equal to Model.findById,
‫like this, right?
‫Then, if there is a populate options object,
‫well, then in that case,
‫query is gonna be
‫query.populate with the populate options, okay?
‫And then, finally we await our query,
‫and save it in the document.
‫So, await query just like this, all right.
‫And so, that's actually it.
‫So, this logic that we have here
‫with not awaiting the query right away,
‫but instead just saving it into a variable,
‫so that we can then, in the next step, manipulate it.
‫We actually already did this kind of stuff before
‫when we were building our API features, right?
‫So, only in the end, when the entire query is ready,
‫we will then await it and store it somewhere in a variable.
‫Now, let's go ahead and actually use this one everywhere,
‫starting of course with the Tour.
‫So, getTour will now be
‫factory.getOne,
‫and pass in the Tour
‫and populate options object, remember that?
‫And so, what we're gonna do is to say path and reviews.
‫Right, so remember that the path property is basically
‫the field that we want to populate,
‫and then we can also specify select,
‫so remember this one, where we specify
‫which of the fields we actually want to get, right?
‫But in this case,
‫we don't have any of that,
‫and so let's just leave it like this.
‫And now, we can actually go ahead and delete all of this.
‫So, great.
‫And, just to make sure, let's actually quickly test this.
‫So, we'll gt a certain Tour,
‫and, indeed, it still works.
‫Let's see if this one had some reviews.
‫Oh, yeah, actually it does, and you see
‫that the population process is also still working.
‫So, that was successful, I would say.
‫And so, now lets also use this getOne
‫in all the other resources.
‫So, the user controller here where we have,
‫let's see where it is, ah, down here.
‫So, let's say factory.getOne,
‫but only with the user model,
‫and no populate options object.
‫Okay, and since we're here,
‫let's actually just change the error message
‫here for create user,
‫so this route is not defined, it never will be,
‫and please use signup instead.
‫Next up, and finally,
‫the same thing for the reviews basically.
‫So, exports.getReview
‫is equal factory.getOne review,
‫and I think we don't have (mumbles) our routes just yet.
‫And, indeed, we don't, so adding this real quick here,
‫reviewController.getReview, okay?
‫Let's just quickly test this one as well,
‫just because I also want to then add it
‫here to Postman, okay?
‫So, just copying this one because it's similar,
‫and then, indeed, it is get.
‫And, yep, works perfectly fine, store it here in reviews,
‫and getReview.
‫All right, an now all that's missing is
‫basically a getAll factory function, right?
‫So, basically, to replace
‫this getAllTours, getAllUsers,
‫which we should also have somewhere here,
‫so getAllUsers, and also getAllReviews,
‫so let's again copy it here from the Tour controller
‫because actually this is the one that is really complete
‫because it has all these API features,
‫and so, after creating our getAll factory function,
‫all of the three resources will then get these API features.
‫So again, copying all of this,
‫exports.getAll,
‫and so now, we will actually have to require
‫these API features here,
‫and in fact we can actually remove it from here
‫because we will no longer need it
‫because we now transfer this to the handler factory, right?
‫Now, here all we need to do is then to replace, as always,
‫with model, and then here,
‫doc and data.
‫Now, okay, perfect.
‫So, let's see if this works,
‫getAll with Tour.
‫And now, I really want to see if this still works
‫with all these features,
‫and so it's here, getAll Tours,
‫and so, let's add our query string here,
‫and let's say duration greater or equal than let's say a 10,
‫and sort by price.
‫Okay, and so we get two results here.
‫Okay, it's not working.
‫Anyway, we get the two (chuckles) results here,
‫and they both have a duration greater than 10,
‫and the price is 1497,
‫and the second one is higher, okay?
‫Let's put it here like to seven,
‫so we get a bit more results.
‫Okay, and now we get five.
‫Okay, anyway, let's now do the same for the reviews
‫because I'm really excited to test out these API features
‫on the reviews as well.
‫Now, one problem that we have here is
‫that this route handler actually has these two lines of code
‫that all the other getAll handlers do not have, okay?
‫But, what we're going to do here is to simply copy this code
‫into our handler factory as well, okay?
‫That's kind of a hack
‫because we really only need this one for getAll reviews,
‫but to get around this would be a bit too much work
‫here in this situation, and once more,
‫I simply want to keep it simple here, all right.
‫So, let's copy this here,
‫and I'm adding a comment here to allow
‫for nested getReviews on Tour, okay?
‫And so this filter, we will then also pass it in here, okay?
‫So again, this is a small hack,
‫but I'm gonna leave it here like this
‫because I think it is reasonable, all right.
‫Anyway, let's now get rid of this,
‫so factory.getAll and review, okay?
‫Let's actually put this down here next to all the others.
‫And now, as you see,
‫we actually do not even need this catchAsync here anymore,
‫so I'm gonna comment it out here
‫because, who knows, maybe in the future we're gonna need it
‫for some other Middleware function here, all right.
‫So, that looks nice and clean,
‫and let's now test out the getAll reviews.
‫All right, so let's actually just save changes here as well.
‫These ones we don't need,
‫but I actually want to get all the reviews.
‫So, right now we have four reviews,
‫and so let's now try to filter for reviews
‫only with a rating of four, let's say.
‫So, query string, rating equal four.
‫Oh, and it actually works,
‫so nice, that's really nice.
‫So, just like this, we get access to all these API features
‫like filtering, sorting, pagination, and all that good stuff
‫that we implemented (chuckles)
‫a long time ago in the course, right?
‫And, I also want to make sure
‫that this getAll reviews on Tour also still works.
‫So, let's check that,
‫and, yeah, you see that it actually does.
‫So, the Tour ID that we have here is
‫exactly the one right here and right here.
‫So, that one is also still working,
‫and so let's finally also use getAll
‫for the user controller, all right.
‫So, basically replacing simply this,
‫so factory.getAll user, all right.
‫And, let's actually put this one
‫here close to the other ones, all right.
‫And, then this one as well,
‫so basically having all of these ones generated
‫by factory functions together,
‫and then all the others simply above them.
‫All right, let's do the same here,
‫this one is already nice and clean,
‫and the same for the Tour controller,
‫so what else do we have here?
‫This one we can get rid of,
‫and, okay, I think it looks nice like this.
‫Again, we can comment out this piece of code
‫because, for now at least, we don't need it anymore.
‫And so, just to test it again here with the users,
‫let's get all of them together,
‫and, indeed, here they are.
‫We can now also say that we only want the ones
‫with the role of user,
‫and, indeed, that works as well.
‫Great, and that actually wraps up this part
‫of creating handler factory functions,
‫and this really was a huge step forwards in our project,
‫so remember that, a bit later,
‫we will also create a booking resource,
‫and so you see that probably we're gonna be able to create
‫the main API for these bookings
‫in like five seconds or something,
‫simply using these five factory functions, all right.
‫Anyway, good work, great job,
‫and I'll see you in the next one.