‫Let's now keep working on our API.
‫Over the next videos, we will implement
‫a couple of common API features
‫that make an API easier and more pleasant to use
‫for whomever is gonna use it.
‫And in this lecture,
‫we're gonna start with filtering.
‫So again, the first feature that we're gonna implement
‫is to allow the user to basically filter data
‫using a query string.
‫Let me just tell you what a query string is using Postman.
‫So, let's close all these guys.
‫Alright.
‫Actually where filtering is gonna make sense
‫is here on this get all tours route.
‫Because, this is the one that,
‫well as the name says, gets all the tours.
‫And so here, we want to allow the user to filter the data,
‫so that instead of getting all the data,
‫he only gets the data that matches the filter.
‫Like this, we can basically allow the user
‫to query the data in a very easy way.
‫Again, using the query string.
‫And the query string looks a bit like this.
‫And I'm sure you've seen it.
‫So we start with a question mark,
‫and then we can simply specify some field value pairs.
‫So let's say we wanted to filter
‫for a duration equal to five and
‫at the same time, a difficulty of easy.
‫So we can very simply build a query string like this.
‫So again, it starts with this question mark,
‫and then we can specify as many
‫key value pairs using this format.
‫And now our Postman application here
‫actually recognizes this and basically
‫parses this string here and puts the key and
‫the values down here in this Params tab.
‫So we could also specify the key and values here.
‫So lets say test, set it to twenty three, and
‫so you see up here that it actually
‫added it to the query string.
‫So that's a very nice way of Postman helping us here.
‫Because now we can, for example, while we're
‫doing testing we can turn these on and off
‫and you see that the query string
‫in here reacts accordingly.
‫Anyway, we now need a way of accessing this data
‫that's in a query string, in our Express application.
‫But, luckily for us, that's very easy,
‫because Express already took care of that.
‫So that's just one of the many many things
‫that Express does for us in order to really make
‫NodeJS development a lot faster.
‫So let me show it to you here, actually in the console.
‫So this data is on a request, which makes sense,
‫and then it is in a field called query.
‫So request dot query should then give us
‫an object nicely formatted with the data
‫from the query string.
‫Give it a save.
‫And note, how I actually added it to
‫the get all tours handler function.
‫So again, we do this kind of filtering
‫in the route where we want to get all the tours.
‫Let's test it out now with this exact query string.
‫Sent the request.
‫And coming back, here we got the object.
‫Let's actually make this here bigger
‫so you can see.
‫That's not really working.
‫So sometimes I know some people cannot see
‫the bottom of the screen.
‫Let me just do it again here.
‫And so, here we go.
‫We have the object, which has the duration set to five
‫and the difficulty set to easy.
‫And so you see that Express, very nicely,
‫parsed that string into this, easy to use, object.
‫Now one thing that I noticed here is that
‫we're actually missing the log that we had
‫easier here in the console.
‫Let's take a look at why that's happening.
‫So for some reason, we now have the application
‫before we actually read the environment variable.
‫That way, the application does not get access to them.
‫I thought that I had fixed this before,
‫but for some reason it's back now.
‫Give it another save here.
‫And I will try that again.
‫Now we get our logging back.
‫A get request to this URL and then with
‫this rest of the data here.
‫Anyway, let's now actually use that data
‫in order to implement our filtering.
‫But before we can do that, I need to tell you that
‫in Mongoose, there are actually two ways of
‫writing database queries.
‫The first one is to just use filter object
‫just like we did in the MongoDB introduction section.
‫Right? Remember that?
‫The second way is to use some special Mongoose methods.
‫Let me just, very quickly, show that to you.
‫With the filter object, we would do it like this.
‫We start with the find here, and then in there
‫we can pass a filter object.
‫And I already mentioned that before.
‫Again, it works the exact same way as
‫with a normal MongoDB query.
‫We could now say, duration
‫set it to five.
‫And then,
‫difficulty, set it to easy.
‫That's exactly the query string we had before,
‫and now I'm hard coding it here just to
‫show you the two different ways of
‫writing queries in Mongoose.
‫Let's test this one out.
‫You see that now, we only get two results.
‫Let's give ourselves some space here.
‫Alright.
‫We see the two results and indeed
‫they both have a duration of five,
‫so here and here, and they both are easy.
‫Easy and easy.
‫So our filter worked just fine.
‫That is the first way of writing a query.
‫Just the normal way that we're already used to,
‫but there is another way.
‫Let me show that to you as well.
‫Again, we start in the exact same way,
‫but then the difference is that we start
‫chaining some special Mongoose method to
‫basically build the query similar to this one that we have.
‫So we say,
‫where
‫the duration
‫equals five.
‫Then also, where
‫the difficulty,
‫that needs to be in quotes,
‫equals
‫easy.
‫This query here is gonna be exactly
‫the same as this one, but again, written using
‫special Mongoose methods.
‫And there are of course tons of other methods.
‫For example, instead of equals, we can have less than,
‫or equal, or just less than, or you can also
‫sort the results or limit the number of results,
‫and really all kinds of stuff.
‫For sure, we're gonna use some of them
‫over the next couple of videos.
‫This might look a bit weird here to you,
‫but its actually very, very useful in some cases.
‫Just to test, give it a try again to this one.
‫And indeed we get our same two results.
‫Now, let me comment this one here out.
‫I'm gonna leave it here just as a reference,
‫because right now, we're gonna use this method here.
‫And we're gonna use it, because in fact,
‫we actually already have an object that
‫looks a lot like this.
‫And that is request dot query.
‫If you compare it, this object,
‫to this object that you see down here,
‫looks exactly the same as this one.
‫To implement a very simple filter,
‫all we have to do in this case is to say, req dot query.
‫Let's try that one more time.
‫Get rid of this here.
‫And indeed we get the exact same two results.
‫Now let's just try only with difficulty set to easy.
‫Now we get four results.
‫All of them of course will have
‫the difficulty set to easy.
‫Our filter, our very basic filter,
‫is now actually working.
‫Now, the problem with this implementation,
‫is that its actually way too simple.
‫That's because, later on, we will have
‫other query parameters.
‫For example, sort, for sorting functionality,
‫or page, for pagination.
‫We need to make sure that we are
‫not querying for these in our database.
‫For example, if we added here,
‫page, equal to two,
‫then we would, of course, not get any result.
‫Let me show that to you.
‫And indeed we do not get any result,
‫because there is no document in this collection
‫where page is set to two.
‫We only want to use this parameter here,
‫or this field, page, to implement pagination
‫and not to actually query in the database.
‫So what we will have to do is,
‫to basically exclude these special field names
‫from our query string before we actually do the filtering.
‫Let's now go ahead and implement that.
‫What we will do is, to first, create a
‫shallow copy of the request dot query object.
‫Let's call it query object.
‫Here we need, really, a hard copy.
‫We can't just do, request dot query,
‫because then, if you would delete something
‫from this object, we would also delete it
‫from the req dot query object.
‫And that's because in JavaScript,
‫when we set a variable to another object,
‫that new variable will basically just be
‫a reference to that original object.
‫So we really need a hard copy here.
‫In JavaScript, there's not really a built-in way
‫of doing this, but a very nice trick that we can use,
‫since ES6, is to use, first, the structuring
‫which we use by using dot dot dot.
‫And then we can simply create a
‫new object out of that.
‫Just like this.
‫This structuring here, these three dots,
‫will basically take all the fields out of the object.
‫Here with the curly braces, well,
‫we simply create a new object.
‫So we have a new object that is basically
‫going to contain all the key value pairs
‫that were in our req dot query object.
‫So that's a copy.
‫Now let's create an array of
‫all the fields that we want to exclude.
‫I'm calling that one excluded fields.
‫And then we want to exclude page,
‫so that's the one that I just
‫told you before in Postman.
‫Then, we also want to exclude
‫sort,
‫we want to exclude limit,
‫and we want to exclude fields.
‫We will implement all of the functionality
‫of paging, sorting, limiting, and selecting
‫only some specific fields, later
‫over the next couple of videos.
‫Next, what we need to do is to
‫basically remove all of these fields
‫from our query object.
‫And in order to do that, we will
‫loop over these fields.
‫So, excluded fields
‫for each.
‫And we're using for each because
‫we don't want to save a new array.
‫Then each of these of elements,
‫we can use the delete operator.
‫And then from the query object,
‫we want to delete the field with
‫the name of element, so the current
‫element in the array.
‫Like this, we will first delete the field of page,
‫then the sort, then the limit, then the fields.
‫Of course, only in case if its there.
‫If there is, for example, no limit field,
‫then, of course, that will not be deleted,
‫because its not there.
‫Let's now take a look if this actually works.
‫I'm gonna log req dot query and
‫at the same time our query object.
‫Giving this a save.
‫Don't worry about our results now.
‫All I want to take a look at is
‫our query object, just to make sure
‫that this logic that we have here actually works.
‫Let's add a sort here of one and a limit of 10.
‫These will make more sense later.
‫For now, I am just adding them,
‫so that I can later exclude them.
‫Results don't matter, all that matters,
‫is that our original query is this one here,
‫and then our query object, which is
‫the one that we're going to use,
‫only has difficulty set to easy.
‫That's because we excluded, page, sort, and limit.
‫This now works, so instead of using
‫req dot query, we're gonna use our query object.
‫Let's get rid of that and try it again.
‫Now we should be back to querying for
‫all the documents that have a difficulty
‫set to easy and ignoring all of these other fields.
‫Send that.
‫And indeed, we are back to our four
‫results that we had before.
‫We can also turn on the duration,
‫and indeed, we will now have two results.
‫Remember that?
‫And if we turn these off,
‫well, then off course its gonna work the same.
‫Let's just delete this empty line here.
‫And so, indeed, with our original query string,
‫things obviously also still worked the same.
‫We prepared our filter feature so that it
‫ignores page, sort, and limit fields.
‫But there is actually something more we need
‫to do in our code, in order to basically
‫be able to implement these features in future videos.
‫Let's go back here to our code.
‫So let's now learn a little bit
‫about how queries actually work in Mongoose.
‫I think I mentioned this before,
‫but its very important to talk about this again.
‫This find method here is going to return a query.
‫All of this here will return a query.
‫And that is the reason why we can then
‫chain other methods like this.
‫Like where, equals, and all these other methods
‫that I talked to you about before.
‫Let me actually show that to you in the documentation again.
‫Here we have the query object,
‫and again, when we use the find method,
‫it will return an object which is a query.
‫So in query dot prototype,
‫we then have all of these methods.
‫For example, down here we have where,
‫which I just mentioned.
‫We have sort which is the one
‫that were gonna use later to sort.
‫We have, let's see, we have less than
‫or less than equal, we have greater.
‫We have...
‫What else did we use?
‫We used equals.
‫All of these are part of query dot prototype.
‫Which, again, refers to objects that
‫we're creating using the query class.
‫Again, this is the reason why
‫we can do this sort of chaining.
‫Now comes the important part.
‫As soon as we actually await the
‫result of the query, so as soon as
‫we use await here or here, for example.
‫As soon as we use this await,
‫the query will then execute and
‫come back with the documents that
‫actually match our query.
‫If we do it like this, such as we have here,
‫then there is now way of, later,
‫implementing sorting, or pagination,
‫or all of these other features.
‫Instead, what we will have to do,
‫is to save this part here into a query,
‫then in the end, as soon as we change all the methods
‫to the query that we need to, only then
‫by the end, we can await that query.
‫For example, we're going to use the sort method.
‫We're going to use the predict method,
‫we're going to use the limit method,
‫and we're going to use, really, a bunch of methods,
‫and chain them to this query.
‫That would be impossible to do,
‫again, if we await the result of
‫this initial query here, right away.
‫I hope that made sense.
‫The way that we will do it
‫is that we
‫will have our tours down here.
‫And this will await the query.
‫The query is, well, simply the
‫query without any await.
‫Just to make it consistent with
‫this part here,
‫let's do it like this.
‫Let's say that,
‫first, we build the query
‫and then we execute the query.
‫That's not correct.
‫Since we're doing comments here,
‫let's also say send
‫response.
‫Just to make our code a bit more easy to scan.
‫I hope that all of this made sense,
‫this turned out to be quite a long video,
‫but it was important to finish
‫this part here by explaining you
‫this logic here, so that in the next videos,
‫we will then be able to implement
‫the rest of the features.
‫Because, again, without having it
‫like this, it would not work.