1 00:00:01,110 --> 00:00:03,330 In this video, we're gonna talk about 2 00:00:03,330 --> 00:00:06,180 the second type of Mongoose middleware, 3 00:00:06,180 --> 00:00:08,133 which is query middleware. 4 00:00:09,690 --> 00:00:12,169 And, as the name says, query middleware 5 00:00:12,169 --> 00:00:15,720 allows us to run functions before or after 6 00:00:15,720 --> 00:00:18,360 a certain query is executed. 7 00:00:18,360 --> 00:00:21,020 And so let's now add a pre-find hook, 8 00:00:21,020 --> 00:00:23,730 so basically, a middleware that is gonna run 9 00:00:23,730 --> 00:00:26,493 before any find query is executed. 10 00:00:29,780 --> 00:00:31,740 So let's add another comment here. 11 00:00:31,740 --> 00:00:35,283 So this is query middleware. 12 00:00:36,270 --> 00:00:38,760 And of course, it works in a very similar way 13 00:00:38,760 --> 00:00:39,763 as before. 14 00:00:41,320 --> 00:00:43,950 So the tourSchema, and then pre, 15 00:00:43,950 --> 00:00:46,280 and in here we define the hook, 16 00:00:46,280 --> 00:00:47,557 which is gonna be "find." 17 00:00:50,110 --> 00:00:52,900 So, function, and again, we have access 18 00:00:52,900 --> 00:00:55,540 to the next function. 19 00:00:55,540 --> 00:00:57,870 And actually, let's start by calling it here 20 00:00:57,870 --> 00:01:00,880 at the end so that we don't forget it. 21 00:01:00,880 --> 00:01:03,310 Okay, and so you see, that it looks 22 00:01:03,310 --> 00:01:05,680 exactly like the other middleware, 23 00:01:05,680 --> 00:01:07,170 the other pre-hook. 24 00:01:07,170 --> 00:01:10,320 The only difference here is really this find hook, 25 00:01:10,320 --> 00:01:12,360 which will make this query middleware 26 00:01:12,360 --> 00:01:14,320 and not document middleware. 27 00:01:14,320 --> 00:01:15,153 All right? 28 00:01:15,153 --> 00:01:17,040 And so, the big difference here is 29 00:01:17,040 --> 00:01:20,910 that the this keyword will now point at the current query 30 00:01:20,910 --> 00:01:22,700 and not at the current document, 31 00:01:22,700 --> 00:01:25,580 because we're not really processing any documents here. 32 00:01:25,580 --> 00:01:28,370 We're really gonna be processing a query. 33 00:01:28,370 --> 00:01:29,203 Okay? 34 00:01:29,203 --> 00:01:32,160 And the use case that we're gonna do here is this. 35 00:01:32,160 --> 00:01:34,380 So let's suppose that we can have 36 00:01:34,380 --> 00:01:36,670 secret tours in our database, 37 00:01:36,670 --> 00:01:39,760 like for tours that are only offered internally, 38 00:01:39,760 --> 00:01:43,160 or for a very small, like, VIP group of people, 39 00:01:43,160 --> 00:01:45,420 and that the public shouldn't know about. 40 00:01:45,420 --> 00:01:47,327 Now, since these tours are secret, 41 00:01:47,327 --> 00:01:51,080 we do not want the secret tours to ever appear 42 00:01:51,080 --> 00:01:52,510 in the result outputs. 43 00:01:52,510 --> 00:01:53,510 Right? 44 00:01:53,510 --> 00:01:56,950 And so what we're gonna do is to create a secret tour field 45 00:01:56,950 --> 00:02:00,780 and then query only for tours that are not secret. 46 00:02:00,780 --> 00:02:01,690 All right? 47 00:02:01,690 --> 00:02:02,763 So, let's do that. 48 00:02:04,160 --> 00:02:07,103 Start by adding here, and let's do it right at the end. 49 00:02:11,447 --> 00:02:15,114 secretTour, so the type should be a Boolean, 50 00:02:16,560 --> 00:02:17,980 and I think this is the first time 51 00:02:17,980 --> 00:02:19,710 we're actually using a Boolean, 52 00:02:19,710 --> 00:02:22,030 so this would either be true or false. 53 00:02:22,030 --> 00:02:23,852 So if it's true, then it is a secret tour, 54 00:02:23,852 --> 00:02:25,770 and we don't want it to show up, 55 00:02:25,770 --> 00:02:29,133 and, by default, it is false. 56 00:02:30,570 --> 00:02:31,403 All right? 57 00:02:31,403 --> 00:02:35,000 And so, basically, usually the tours are not secret. 58 00:02:35,000 --> 00:02:35,950 Okay. 59 00:02:35,950 --> 00:02:39,740 Next up, let's actually go ahead and create a secret tour 60 00:02:40,900 --> 00:02:44,610 so that we can then test using it, okay? 61 00:02:44,610 --> 00:02:49,610 So let's call this here the Super Secret Tour. 62 00:02:50,530 --> 00:02:51,880 All of this doesn't matter, 63 00:02:54,130 --> 00:02:58,603 and let me just say that secretTour is indeed true. 64 00:02:59,700 --> 00:03:01,020 Okay? 65 00:03:01,020 --> 00:03:02,443 Save it here ... 66 00:03:03,480 --> 00:03:05,980 And, uh, where is that? 67 00:03:05,980 --> 00:03:08,520 Yeah. So secretTour is true. 68 00:03:08,520 --> 00:03:10,750 And let's now actually head over to Compass 69 00:03:10,750 --> 00:03:13,783 and delete all of these other tours that we had there. 70 00:03:15,600 --> 00:03:17,483 So, let's reload this ... 71 00:03:18,890 --> 00:03:22,813 And then, down here, we should have ... 72 00:03:24,470 --> 00:03:27,890 Yeah, this test tour here, we can delete that. 73 00:03:27,890 --> 00:03:29,613 Another test tour ... 74 00:03:30,740 --> 00:03:32,540 So all this clutter here, basically, 75 00:03:33,730 --> 00:03:35,530 we want to get rid of it. 76 00:03:35,530 --> 00:03:37,600 We only keep the secretTour here 77 00:03:37,600 --> 00:03:40,010 so that we can now experiment with it. 78 00:03:40,010 --> 00:03:43,170 Okay, and you see here that secretTour is set to true, 79 00:03:43,170 --> 00:03:44,530 while the other ones, of course, 80 00:03:44,530 --> 00:03:46,180 do not have this attribute, 81 00:03:46,180 --> 00:03:48,110 because, by the time we created them, 82 00:03:48,110 --> 00:03:49,993 we didn't have the secretTour yet. 83 00:03:51,780 --> 00:03:54,060 So, now, just before we start, 84 00:03:54,060 --> 00:03:57,539 back in Postman, let's confirm that, indeed, 85 00:03:57,539 --> 00:04:01,230 the last tour here, and actually it's not the last tour, 86 00:04:01,230 --> 00:04:02,660 so where is it? 87 00:04:02,660 --> 00:04:03,570 Oh, it's the first one. 88 00:04:03,570 --> 00:04:05,950 So here we have the Super Secret Tour, 89 00:04:05,950 --> 00:04:07,483 of course, set to true. 90 00:04:08,360 --> 00:04:12,010 All right? So, moving back now, 91 00:04:12,010 --> 00:04:13,880 let's now execute the query 92 00:04:13,880 --> 00:04:15,580 like we just said in the beginning. 93 00:04:15,580 --> 00:04:18,350 So, again, keep in mind that this here 94 00:04:18,350 --> 00:04:20,780 is now a query object, all right? 95 00:04:20,780 --> 00:04:23,230 And so we can chain all of the methods 96 00:04:23,230 --> 00:04:25,250 that we have for queries. 97 00:04:25,250 --> 00:04:29,220 And so that simply adds a find method here, 98 00:04:29,220 --> 00:04:31,260 and then basically select all the documents 99 00:04:31,260 --> 00:04:36,070 where secretTour is not true, okay? 100 00:04:36,070 --> 00:04:40,540 So secretTour ... 101 00:04:40,540 --> 00:04:43,530 And then is not equal to true. 102 00:04:43,530 --> 00:04:45,710 And I'm doing it like this because, remember, 103 00:04:45,710 --> 00:04:49,170 the editors are not currently set to false. 104 00:04:49,170 --> 00:04:51,120 They do simply not have this attribute. 105 00:04:52,090 --> 00:04:53,100 All right? 106 00:04:53,100 --> 00:04:56,210 Okay, so let's test it out now again. 107 00:04:56,210 --> 00:04:58,263 And so it should now be gone here. 108 00:04:59,220 --> 00:05:01,483 And indeed, it is no longer here. 109 00:05:02,320 --> 00:05:05,570 Okay, we have all the tours that are not secret, 110 00:05:05,570 --> 00:05:07,290 but not the secret tour. 111 00:05:07,290 --> 00:05:08,943 And I'm now seeing that we actually have 112 00:05:08,943 --> 00:05:11,370 secretTour set to false here, 113 00:05:11,370 --> 00:05:13,850 but that's really just a Mongoose thing, 114 00:05:13,850 --> 00:05:17,913 so let's take another look here at Compass, 115 00:05:18,830 --> 00:05:19,753 and reload. 116 00:05:20,800 --> 00:05:22,920 And so you see that, actually, in the database, 117 00:05:22,920 --> 00:05:25,450 secretTour is not set to false. 118 00:05:25,450 --> 00:05:27,890 Mongoose is simply adding that because we have it 119 00:05:27,890 --> 00:05:30,478 in our schema as the default, and it's not in the database. 120 00:05:30,478 --> 00:05:34,360 And so it's basically, then, putting it there anyway. 121 00:05:34,360 --> 00:05:37,150 So you see that we actually have 11 documents, 122 00:05:37,150 --> 00:05:40,710 but then here in Postman we only get ten results. 123 00:05:40,710 --> 00:05:41,600 And that is, of course, 124 00:05:41,600 --> 00:05:45,360 because our Secret Tour is basically filtered out. 125 00:05:45,360 --> 00:05:46,193 Okay? 126 00:05:46,193 --> 00:05:47,910 So, let's try to understand again 127 00:05:47,910 --> 00:05:49,320 what really happens. 128 00:05:49,320 --> 00:05:51,730 So as soon as we hit this route, here, 129 00:05:51,730 --> 00:05:53,170 using the get method, 130 00:05:53,170 --> 00:05:55,313 let's see what happens. 131 00:05:57,520 --> 00:06:00,340 So, what happens is that we create a query 132 00:06:00,340 --> 00:06:02,700 using tour.find. 133 00:06:02,700 --> 00:06:03,533 Okay? 134 00:06:03,533 --> 00:06:05,900 And then, of course, we chain all these methods to it 135 00:06:05,900 --> 00:06:08,660 as we talked about in one of the last lectures, 136 00:06:08,660 --> 00:06:09,790 and then, by the end, 137 00:06:09,790 --> 00:06:13,770 we then execute that query here by using await. 138 00:06:13,770 --> 00:06:15,280 Right? Remember that? 139 00:06:15,280 --> 00:06:17,460 So this is where we execute the query. 140 00:06:17,460 --> 00:06:20,030 But, before it actually is executed, 141 00:06:20,030 --> 00:06:24,790 then, our pre-find middleware here is executed. 142 00:06:24,790 --> 00:06:25,623 Okay? 143 00:06:25,623 --> 00:06:27,873 And it is executed because it is find, 144 00:06:27,873 --> 00:06:30,270 just like we used here. 145 00:06:30,270 --> 00:06:31,103 Right? 146 00:06:31,103 --> 00:06:33,020 So, we're creating a find query, 147 00:06:33,020 --> 00:06:36,570 and so, therefore, the find hook is then executed. 148 00:06:36,570 --> 00:06:39,420 Then, in here, since it is query middleware, 149 00:06:39,420 --> 00:06:41,630 the this keyword points to the query. 150 00:06:41,630 --> 00:06:43,670 And so, to that query, we can then chain 151 00:06:43,670 --> 00:06:46,230 yet another find method, right? 152 00:06:46,230 --> 00:06:49,160 And in there, we then filter out the secretTour 153 00:06:49,160 --> 00:06:50,930 using this filter object. 154 00:06:50,930 --> 00:06:51,763 Okay? 155 00:06:51,763 --> 00:06:54,280 So basically saying that we only want tours 156 00:06:54,280 --> 00:06:57,450 where the secretTour is not equal to true. 157 00:06:57,450 --> 00:06:59,120 And it would actually work the same 158 00:06:59,120 --> 00:07:00,979 if we simply said here, false, 159 00:07:00,979 --> 00:07:03,790 but I find it cleaner like this. 160 00:07:03,790 --> 00:07:07,660 Okay, there is now just one thing that we need to fix, 161 00:07:07,660 --> 00:07:10,140 because right now this middleware is running 162 00:07:10,140 --> 00:07:13,010 for find, but not for find1. 163 00:07:13,010 --> 00:07:13,843 Okay? 164 00:07:13,843 --> 00:07:17,023 So let me show you the problem that we might get with that. 165 00:07:18,270 --> 00:07:23,120 So, uh, let's take the ID of the Secret Tour. 166 00:07:23,120 --> 00:07:24,570 So we have the Secret Tour here, 167 00:07:24,570 --> 00:07:29,570 and that's its ID, and so if we get tour, 168 00:07:31,370 --> 00:07:35,040 then that should give us the Super Secret Tour here. 169 00:07:35,040 --> 00:07:35,873 Right? 170 00:07:35,873 --> 00:07:37,383 And so you see, that that filter 171 00:07:37,383 --> 00:07:39,470 that we just built in the middleware 172 00:07:39,470 --> 00:07:41,630 is not working for this command. 173 00:07:41,630 --> 00:07:42,463 Okay? 174 00:07:42,463 --> 00:07:45,640 And that's because the handle function for this route, 175 00:07:45,640 --> 00:07:47,360 as you might remember, 176 00:07:47,360 --> 00:07:51,560 is using findByID, which, behind the scenes, 177 00:07:51,560 --> 00:07:55,290 is find1, and so it's different from find. 178 00:07:55,290 --> 00:07:56,242 All right? 179 00:07:56,242 --> 00:08:01,242 So, we need to specify the same middleware also for find1. 180 00:08:01,750 --> 00:08:03,610 Now, there are two ways of doing that, 181 00:08:03,610 --> 00:08:06,760 and the first one would be simply to go ahead, 182 00:08:06,760 --> 00:08:11,363 copy this code, and then put find1 here. 183 00:08:12,210 --> 00:08:14,210 But that's not really good, 184 00:08:14,210 --> 00:08:16,970 and so instead we're gonna use a regular expression. 185 00:08:16,970 --> 00:08:20,530 And that is quite easy, and so ... 186 00:08:20,530 --> 00:08:22,700 And let me actually just duplicate this here, 187 00:08:22,700 --> 00:08:24,013 comment this piece out, 188 00:08:25,495 --> 00:08:28,360 and then, remember, a regular expression 189 00:08:28,360 --> 00:08:30,550 starts and ends with a slash. 190 00:08:30,550 --> 00:08:32,500 And then in here, what I want to say, 191 00:08:32,500 --> 00:08:34,437 is that this middleware should be executed 192 00:08:34,437 --> 00:08:36,510 not only for find, 193 00:08:36,510 --> 00:08:40,450 but for all the commands that start with the name find. 194 00:08:40,450 --> 00:08:41,283 Okay? 195 00:08:41,283 --> 00:08:45,330 So, find, and find1, and also find1 and delete, 196 00:08:45,330 --> 00:08:46,830 find1 and update, 197 00:08:46,830 --> 00:08:49,400 and so all of these will now actually trigger 198 00:08:49,400 --> 00:08:51,550 this middleware function that we have here. 199 00:08:52,760 --> 00:08:53,890 All right? 200 00:08:53,890 --> 00:08:55,580 So, no need for that. 201 00:08:55,580 --> 00:08:58,510 This regular expression here is way better. 202 00:08:58,510 --> 00:08:59,878 So again, this here simply means 203 00:08:59,878 --> 00:09:03,000 all the strings that start with find. 204 00:09:03,000 --> 00:09:05,140 And actually, since we're here, 205 00:09:05,140 --> 00:09:07,883 let me show you the Mongoose documentations again. 206 00:09:08,970 --> 00:09:13,240 So, when we go here, to middleware in these guides, 207 00:09:13,240 --> 00:09:15,670 you'll then have an overview of all the middleware. 208 00:09:15,670 --> 00:09:16,557 For example, document middleware 209 00:09:16,557 --> 00:09:19,041 is the one that we talked about before, 210 00:09:19,041 --> 00:09:21,640 which runs, for example, on save. 211 00:09:21,640 --> 00:09:23,600 But in fact, document middleware can also 212 00:09:23,600 --> 00:09:26,510 run for stuff like remove. 213 00:09:26,510 --> 00:09:27,460 All right? 214 00:09:27,460 --> 00:09:28,840 Or for validate. 215 00:09:28,840 --> 00:09:31,220 Okay, but I didn't talk about these because 216 00:09:31,220 --> 00:09:34,750 usually the one that we always use is just for save. 217 00:09:34,750 --> 00:09:37,590 Now, query middleware can run for 218 00:09:37,590 --> 00:09:39,340 all of these query functions. 219 00:09:39,340 --> 00:09:41,980 So find, as we just specified, 220 00:09:41,980 --> 00:09:43,780 and now, with our regular expression, 221 00:09:43,780 --> 00:09:45,520 it's also gonna run for find1, 222 00:09:45,520 --> 00:09:47,270 findOneAndDelete, findOneAndRemove, 223 00:09:48,768 --> 00:09:50,518 and findOneAndUpdate. 224 00:09:51,850 --> 00:09:55,130 Anyway, moving back to Postman now, 225 00:09:55,130 --> 00:09:58,650 this should now have fixed this situation here. 226 00:09:58,650 --> 00:10:01,210 So when we now run this query, 227 00:10:01,210 --> 00:10:03,040 it should have no results. 228 00:10:03,040 --> 00:10:04,800 And indeed, it doesn't. 229 00:10:04,800 --> 00:10:08,220 Because, remember, we were trying to get a secretTour. 230 00:10:08,220 --> 00:10:10,370 So the tour with this ID here is secret, 231 00:10:10,370 --> 00:10:12,520 but we never want the secretTours 232 00:10:12,520 --> 00:10:14,380 to show up in any query. 233 00:10:14,380 --> 00:10:17,283 And so that's why, right now, we get zero results. 234 00:10:18,190 --> 00:10:19,023 Okay? 235 00:10:19,023 --> 00:10:20,510 So that works now. 236 00:10:20,510 --> 00:10:22,160 Don't save this, 237 00:10:22,160 --> 00:10:24,230 and now, back to our code. 238 00:10:24,230 --> 00:10:25,900 Let's now actually also specify 239 00:10:25,900 --> 00:10:28,333 a post middleware for find. 240 00:10:30,140 --> 00:10:35,140 So, tourSchema, and then, just like before, post, 241 00:10:35,820 --> 00:10:38,510 and then let's use our regular expression here again 242 00:10:38,510 --> 00:10:41,113 for anything starting with find. 243 00:10:43,340 --> 00:10:45,240 And then just a regular function, 244 00:10:45,240 --> 00:10:47,400 and then here, in the post-find middleware, 245 00:10:47,400 --> 00:10:49,810 we actually get access to all the documents 246 00:10:49,810 --> 00:10:51,713 that we returned from the query. 247 00:10:52,680 --> 00:10:54,573 So let's call that Docs. 248 00:10:55,680 --> 00:10:56,780 All right? 249 00:10:56,780 --> 00:10:59,350 So, remember that this middleware is gonna run 250 00:10:59,350 --> 00:11:02,280 after the query has already executed. 251 00:11:02,280 --> 00:11:04,100 And so, therefore, it can have access 252 00:11:04,100 --> 00:11:06,120 to the documents that were returned. 253 00:11:06,120 --> 00:11:07,900 Again, because that query has 254 00:11:07,900 --> 00:11:10,033 actually already finished at this point. 255 00:11:11,580 --> 00:11:15,510 So let's log these documents to the console, 256 00:11:15,510 --> 00:11:16,343 so docs, 257 00:11:16,343 --> 00:11:20,360 but I also want to do something else here. 258 00:11:20,360 --> 00:11:22,710 So basically, let's create, kind of, 259 00:11:22,710 --> 00:11:25,150 a clock to measure how long it takes 260 00:11:25,150 --> 00:11:27,163 to execute the current query. 261 00:11:28,120 --> 00:11:28,953 All right? 262 00:11:28,953 --> 00:11:30,770 So, how are we gonna do that? 263 00:11:30,770 --> 00:11:32,680 Well, quite simple. 264 00:11:32,680 --> 00:11:36,180 We can simply set a property onto the this object, 265 00:11:36,180 --> 00:11:39,810 because this query object is really just a regular object. 266 00:11:39,810 --> 00:11:42,570 Of course it has access to all these methods, 267 00:11:42,570 --> 00:11:43,760 such as find, 268 00:11:43,760 --> 00:11:45,020 but we can also use it 269 00:11:45,020 --> 00:11:47,283 to set any property that we want on it. 270 00:11:48,660 --> 00:11:51,000 So, again, just a regular object. 271 00:11:51,000 --> 00:11:53,410 And so here we can say this.start 272 00:11:53,410 --> 00:11:55,333 should be the current date. 273 00:11:56,410 --> 00:11:57,243 Okay? 274 00:11:57,243 --> 00:11:59,380 And so this will set it as the 275 00:11:59,380 --> 00:12:02,150 current time in milliseconds, okay? 276 00:12:02,150 --> 00:12:05,320 And so then, here, in the post middleware, 277 00:12:05,320 --> 00:12:08,200 which is gonna run after the query has executed, 278 00:12:08,200 --> 00:12:10,310 we can then subtract the current time 279 00:12:10,310 --> 00:12:11,603 minus the start time. 280 00:12:14,640 --> 00:12:15,833 So console.log, 281 00:12:18,470 --> 00:12:19,583 query took, 282 00:12:21,240 --> 00:12:22,600 and now the current date 283 00:12:26,970 --> 00:12:28,073 minus this.start, 284 00:12:33,400 --> 00:12:34,423 milliseconds. 285 00:12:35,510 --> 00:12:38,295 Okay, let's give it a save, 286 00:12:38,295 --> 00:12:43,295 and so let's now try to run a query and see our results. 287 00:12:45,090 --> 00:12:46,469 Okay? 288 00:12:46,469 --> 00:12:48,390 So, here we get all our tours, 289 00:12:48,390 --> 00:12:49,713 here we have the console, 290 00:12:50,700 --> 00:12:52,140 and let's actually clear that. 291 00:12:52,140 --> 00:12:53,740 There's a lot of stuff in there. 292 00:12:55,540 --> 00:12:56,763 Request again, 293 00:12:58,340 --> 00:13:00,480 and so here are all the results. 294 00:13:00,480 --> 00:13:03,210 So basically these are all the tours that were found, 295 00:13:03,210 --> 00:13:06,490 and so that's the result of console.log of the docs. 296 00:13:06,490 --> 00:13:09,890 So basically the documents that matched the query. 297 00:13:09,890 --> 00:13:13,220 But I'm now interested in this first console.log, 298 00:13:13,220 --> 00:13:17,670 and so, here we see "Query took 120 milliseconds," 299 00:13:17,670 --> 00:13:19,970 and so that was basically the time that passed 300 00:13:19,970 --> 00:13:22,660 from the beginning, where we defined this, 301 00:13:22,660 --> 00:13:26,950 to after the query has executed, at this point in time. 302 00:13:26,950 --> 00:13:27,783 All right. 303 00:13:27,783 --> 00:13:29,910 And that is all that I had to show you for now 304 00:13:29,910 --> 00:13:31,550 about query middleware, 305 00:13:31,550 --> 00:13:32,680 and just like before, 306 00:13:32,680 --> 00:13:34,370 of course we're gonna use this a lot 307 00:13:34,370 --> 00:13:35,380 throughout the course, 308 00:13:35,380 --> 00:13:37,450 because, as I mentioned in the beginning, 309 00:13:37,450 --> 00:13:39,840 middleware is really a fundamental concept 310 00:13:39,840 --> 00:13:42,010 that's really important for a lot of stuff 311 00:13:42,010 --> 00:13:44,060 that we need in our applications. 312 00:13:44,060 --> 00:13:46,140 So we're almost done talking about middleware. 313 00:13:46,140 --> 00:13:48,070 Next up is the last one, 314 00:13:48,070 --> 00:13:49,823 which is aggregation middleware.