1 00:00:01,100 --> 00:00:02,860 Just like Express, 2 00:00:02,860 --> 00:00:06,080 Mongoose also has the concept of middleware. 3 00:00:06,080 --> 00:00:08,270 And so let's now learn about the first type 4 00:00:08,270 --> 00:00:11,163 of middleware, which is document middleware. 5 00:00:12,830 --> 00:00:15,330 Now, just like with Express, we can use 6 00:00:15,330 --> 00:00:17,860 Mongoose middleware to make something happen 7 00:00:17,860 --> 00:00:19,430 between two events. 8 00:00:19,430 --> 00:00:22,740 For example, each time a new document is saved 9 00:00:22,740 --> 00:00:25,740 to the database, we can run a function 10 00:00:25,740 --> 00:00:29,450 between the save command is issued and the actual saving 11 00:00:29,450 --> 00:00:33,480 of the document, or also after the actual saving. 12 00:00:33,480 --> 00:00:35,820 And that's the reason why Mongoose middleware 13 00:00:35,820 --> 00:00:38,590 is also called pre and post hooks. 14 00:00:38,590 --> 00:00:41,140 So again, because we can define functions 15 00:00:41,140 --> 00:00:44,710 to run before or after a certain event, 16 00:00:44,710 --> 00:00:47,100 like saving a document to the database. 17 00:00:47,100 --> 00:00:52,100 So middleware is an absolutely fundamental concept 18 00:00:52,100 --> 00:00:55,180 in Mongoose, so just like in Express. 19 00:00:55,180 --> 00:00:57,190 And there are tons of possibilities 20 00:00:57,190 --> 00:00:59,780 and use cases for middleware, and we're gonna be 21 00:00:59,780 --> 00:01:02,540 using middleware all the time in this project. 22 00:01:02,540 --> 00:01:06,050 So there are four types of middleware in Mongoose: 23 00:01:06,050 --> 00:01:10,080 document, query, aggregate, and model middleware. 24 00:01:10,080 --> 00:01:12,110 And in this lecture, we're gonna talk about 25 00:01:12,110 --> 00:01:14,410 document middleware, which is middleware 26 00:01:14,410 --> 00:01:18,110 that can act on the currently processed document. 27 00:01:18,110 --> 00:01:20,920 So just like the virtual properties, 28 00:01:20,920 --> 00:01:23,613 we define a middleware on the schema, 29 00:01:25,800 --> 00:01:28,543 so tourSchema.pre. 30 00:01:30,030 --> 00:01:32,850 And so this is for pre middleware, which again, 31 00:01:32,850 --> 00:01:35,450 is gonna run before an actual event. 32 00:01:35,450 --> 00:01:39,360 And that event in this case is the save event. 33 00:01:39,360 --> 00:01:41,350 And so this call back function that we're 34 00:01:41,350 --> 00:01:42,613 gonna define here next, 35 00:01:43,870 --> 00:01:44,820 so function 36 00:01:48,200 --> 00:01:51,980 so this function will be called before an actual document 37 00:01:51,980 --> 00:01:53,943 is saved to the database. 38 00:01:55,407 --> 00:02:00,407 So this is document middleware, 39 00:02:02,010 --> 00:02:05,910 and it runs, let me write all of that here. 40 00:02:05,910 --> 00:02:09,640 So it runs before the save command 41 00:02:10,550 --> 00:02:13,953 and the .create command. 42 00:02:14,860 --> 00:02:17,040 But not on insert many. 43 00:02:17,040 --> 00:02:22,040 So if we use this command here, so insertMany, 44 00:02:22,450 --> 00:02:26,153 then that will actually not trigger the save middleware. 45 00:02:27,600 --> 00:02:29,140 So always keep that in mind. 46 00:02:29,140 --> 00:02:32,780 It's very important to realize that only on save 47 00:02:32,780 --> 00:02:35,560 and on create actually this middleware here 48 00:02:35,560 --> 00:02:36,943 is gonna be executed. 49 00:02:38,929 --> 00:02:41,740 And so let's start by doing a simple console.log 50 00:02:42,670 --> 00:02:45,253 and what I'm gonna log through the console is this. 51 00:02:46,350 --> 00:02:49,870 And so in a save middleware, the disk keyword here 52 00:02:49,870 --> 00:02:53,100 is gonna point to the currently processed document. 53 00:02:53,100 --> 00:02:56,640 And that is the reason why it is called document middleware. 54 00:02:56,640 --> 00:02:58,740 Again, because in this function here, 55 00:02:58,740 --> 00:03:02,470 we have access to the document that is being processed. 56 00:03:02,470 --> 00:03:05,133 So in this case, the document that is being saved. 57 00:03:06,078 --> 00:03:09,240 And so let me just very quickly show that to you 58 00:03:09,240 --> 00:03:11,300 using this console.log. 59 00:03:11,300 --> 00:03:13,610 And so in order to now trigger this function, 60 00:03:13,610 --> 00:03:17,800 remember we need to run a save command or a create command. 61 00:03:17,800 --> 00:03:22,020 And so we now need to create a new tour using our API 62 00:03:22,020 --> 00:03:26,013 in order to, yeah, to then trigger this middleware. 63 00:03:27,680 --> 00:03:32,680 So let's go here to, to postman, and I'm gonna start by 64 00:03:33,880 --> 00:03:36,830 by saving these two new routes that we created 65 00:03:38,450 --> 00:03:42,313 in the previous lectures, so get monthly plan. 66 00:03:47,300 --> 00:03:52,300 And this one here is get tour stats. 67 00:03:56,031 --> 00:03:59,523 So now I can close them and create new tour. 68 00:04:00,430 --> 00:04:03,060 And we specify the data here in the body. 69 00:04:03,060 --> 00:04:06,300 Now not all of the stuff here is actually required, 70 00:04:06,300 --> 00:04:08,730 so let's take a look at what actually is required 71 00:04:08,730 --> 00:04:11,040 and get rid of the rest. 72 00:04:11,040 --> 00:04:13,483 So the imageCover is required, the summary, 73 00:04:14,610 --> 00:04:18,500 of course the price, and yeah. 74 00:04:18,500 --> 00:04:20,830 So let's get rid of the stuff that we don't 75 00:04:21,760 --> 00:04:24,483 really need here just to keep it at a minimum. 76 00:04:26,000 --> 00:04:28,730 So the ratings, quantity, average, 77 00:04:28,730 --> 00:04:30,080 so these are not necessary. 78 00:04:36,550 --> 00:04:38,490 So I'm just gonna call this one here 79 00:04:38,490 --> 00:04:43,490 the test tour, just to keep it really simple here. 80 00:04:45,702 --> 00:04:49,370 Now let's send this request and indeed, 81 00:04:49,370 --> 00:04:52,420 it created the new document and now let's take a look 82 00:04:52,420 --> 00:04:56,370 at our console and see that document here. 83 00:04:56,370 --> 00:04:58,650 And indeed, here it is. 84 00:04:58,650 --> 00:05:01,540 So let's increase this here a little bit 85 00:05:01,540 --> 00:05:04,900 and so this is what our document is looking like 86 00:05:04,900 --> 00:05:08,510 right before it saved into the database. 87 00:05:08,510 --> 00:05:11,710 And so here we have ratingsAverage and quantity, 88 00:05:11,710 --> 00:05:13,500 which are set by default. 89 00:05:13,500 --> 00:05:17,077 Remember, so 4.5 and zero, and then 90 00:05:19,185 --> 00:05:21,930 the createdAt time stamp, and you can even 91 00:05:21,930 --> 00:05:24,523 see the virtual property that we defined here. 92 00:05:25,700 --> 00:05:28,100 So again, this is right before we actually 93 00:05:28,100 --> 00:05:30,140 save this data to the database. 94 00:05:30,140 --> 00:05:31,410 And so at this point of time, 95 00:05:31,410 --> 00:05:34,600 we can still act on the data before it is then saved 96 00:05:34,600 --> 00:05:36,920 to the database and that is exactly 97 00:05:36,920 --> 00:05:38,173 what we're gonna do now. 98 00:05:39,520 --> 00:05:43,240 So down here in our middleware function. 99 00:05:43,240 --> 00:05:45,900 And what I wanna do here is to create a slug 100 00:05:45,900 --> 00:05:48,120 for each of these documents. 101 00:05:48,120 --> 00:05:50,080 So remember how in the first section, 102 00:05:50,080 --> 00:05:52,510 we created a slug for each of the products 103 00:05:52,510 --> 00:05:54,313 that we had in the store. 104 00:05:55,180 --> 00:05:57,860 And so a slug is basically just a string 105 00:05:57,860 --> 00:06:01,590 that we can put in the URL, usually based on 106 00:06:01,590 --> 00:06:03,570 some string like the name. 107 00:06:03,570 --> 00:06:05,780 So in this case, we're gonna create a slug 108 00:06:05,780 --> 00:06:07,433 based here on the tour name. 109 00:06:09,150 --> 00:06:14,150 So remember how for that we used the slugify package. 110 00:06:14,210 --> 00:06:16,360 And so let's now go ahead and install that. 111 00:06:20,120 --> 00:06:22,063 All right, and while that's doing, 112 00:06:23,430 --> 00:06:25,743 let's go ahead and then require it here. 113 00:06:33,270 --> 00:06:34,980 So require slugify. 114 00:06:39,100 --> 00:06:41,893 Let's go back to our first window here, actually. 115 00:06:43,530 --> 00:06:46,220 And now, down here, we no longer want 116 00:06:46,220 --> 00:06:48,550 to log this to the console. 117 00:06:48,550 --> 00:06:51,720 But instead we can now say this, and remember, 118 00:06:51,720 --> 00:06:54,840 this is the currently processed document. 119 00:06:54,840 --> 00:06:58,060 So we can now define a new property on it. 120 00:06:58,060 --> 00:06:59,860 And that's exactly what I'm doing. 121 00:06:59,860 --> 00:07:03,250 So this.slug should be slugify, 122 00:07:06,210 --> 00:07:08,390 and then just a string that we want to create 123 00:07:08,390 --> 00:07:13,390 a slug out of, and so that's gonna be this.name 124 00:07:13,470 --> 00:07:15,890 and then we also want to pass in the option 125 00:07:15,890 --> 00:07:18,653 that everything should be converted to lower case, 126 00:07:19,970 --> 00:07:24,220 and so that's lower: true, and now I'll give it a save. 127 00:07:24,220 --> 00:07:26,290 And one thing that we didn't talk about yet 128 00:07:26,290 --> 00:07:28,710 is the next function. 129 00:07:28,710 --> 00:07:32,440 So just like in Express, we also have the next function 130 00:07:32,440 --> 00:07:35,300 in mMngoose middleware, basically to call the next 131 00:07:35,300 --> 00:07:37,780 middleware in the stack as we already know. 132 00:07:37,780 --> 00:07:40,680 Now in this case, we only have one middleware function, 133 00:07:40,680 --> 00:07:43,100 which is why we didn't run into any problems, 134 00:07:43,100 --> 00:07:46,433 even not calling next, but let's actually now do that. 135 00:07:47,470 --> 00:07:50,040 And so each middleware function, in a pre save 136 00:07:50,040 --> 00:07:52,723 middleware has access to next. 137 00:07:54,492 --> 00:07:57,700 So that's exactly the same as in Express, 138 00:07:57,700 --> 00:08:01,070 and so by the end of the middleware we call next, 139 00:08:01,070 --> 00:08:03,300 and that will then call the next middleware 140 00:08:03,300 --> 00:08:04,583 in the stack. 141 00:08:04,583 --> 00:08:07,540 So let's try this out again. 142 00:08:07,540 --> 00:08:10,556 And this is gonna be called test tour number two. 143 00:08:10,556 --> 00:08:13,770 Very simple, send to sky, 144 00:08:13,770 --> 00:08:16,900 and let's wait for it. 145 00:08:16,900 --> 00:08:20,930 And now for some reason, it's not really here. 146 00:08:20,930 --> 00:08:22,950 Let's see if we got some error, 147 00:08:22,950 --> 00:08:24,630 and we actually did not. 148 00:08:24,630 --> 00:08:27,570 But the reason why it's not working 149 00:08:27,570 --> 00:08:31,913 is that right now we don't have any slug in our schema. 150 00:08:31,913 --> 00:08:35,360 And remember this actually happened to us before 151 00:08:35,360 --> 00:08:38,150 when we only had a couple of fields in the schema. 152 00:08:38,150 --> 00:08:40,150 And when we, then we'll define some fields 153 00:08:40,150 --> 00:08:42,450 that were not in the schema, then they were 154 00:08:42,450 --> 00:08:44,770 simply not persisted to the database. 155 00:08:44,770 --> 00:08:47,070 And the same thing is now happening here, 156 00:08:47,070 --> 00:08:50,670 so we defined the slug property, but it's not in our schema. 157 00:08:50,670 --> 00:08:54,200 And therefore it was then not saved to the database, 158 00:08:54,200 --> 00:08:56,990 and so let's quickly fix that and let's put it, 159 00:08:56,990 --> 00:08:59,490 oh, I don't know, it doesn't really matter, 160 00:08:59,490 --> 00:09:01,373 can put it here right after the name, 161 00:09:03,210 --> 00:09:06,253 so the slug should simply be a string. 162 00:09:08,443 --> 00:09:10,363 And so that should fix it. 163 00:09:11,610 --> 00:09:14,823 So let's go back and create the test tour number three. 164 00:09:15,880 --> 00:09:18,220 Because it cannot be the same, because remember 165 00:09:18,220 --> 00:09:20,453 we cannot have tours with the same name. 166 00:09:22,260 --> 00:09:26,290 So do it again, and now indeed we have the slug property 167 00:09:26,290 --> 00:09:29,900 right here and it is indeed based on the name, 168 00:09:29,900 --> 00:09:31,170 as you can see here. 169 00:09:31,170 --> 00:09:33,853 Great, so let's go back here, 170 00:09:34,770 --> 00:09:36,463 gonna reduce this a little bit. 171 00:09:37,480 --> 00:09:40,957 And so here we have the pre document middleware. 172 00:09:40,957 --> 00:09:44,000 Let's now just very quickly experiment, also, 173 00:09:44,000 --> 00:09:45,593 with a post middleware. 174 00:09:47,700 --> 00:09:52,700 So tourSchema.post and let's use save again. 175 00:09:55,487 --> 00:09:58,740 And then the callback function, 176 00:09:58,740 --> 00:10:01,090 which in the case of post middleware 177 00:10:01,090 --> 00:10:03,860 has access not only to next, but also to 178 00:10:03,860 --> 00:10:06,823 the document that was just saved to the database. 179 00:10:07,690 --> 00:10:10,883 So let's call that one doc and then next. 180 00:10:12,193 --> 00:10:14,650 And so post middleware functions 181 00:10:14,650 --> 00:10:17,750 are executed after all the pre middleware functions 182 00:10:17,750 --> 00:10:20,090 have completed, all right. 183 00:10:20,090 --> 00:10:23,440 So in here we actually no longer have the disk keyword, 184 00:10:23,440 --> 00:10:25,910 but instead we have the basically finished 185 00:10:25,910 --> 00:10:27,853 document here in doc. 186 00:10:30,960 --> 00:10:34,650 So let's just log that finished document 187 00:10:34,650 --> 00:10:37,640 to the console and then call next. 188 00:10:37,640 --> 00:10:39,713 Now in this case again, we only have one 189 00:10:39,713 --> 00:10:43,200 post middleware and so we wouldn't really need next, 190 00:10:43,200 --> 00:10:46,860 but it's a best practice to simply always include it. 191 00:10:46,860 --> 00:10:50,310 Now another thing that I wanted to show you 192 00:10:50,310 --> 00:10:52,470 is that we can have, of course, multiple 193 00:10:52,470 --> 00:10:56,283 pre middlewares or also post middlewares for the same hook. 194 00:10:57,270 --> 00:11:01,820 And hook is what we call this save here. 195 00:11:01,820 --> 00:11:04,690 So this middleware here is basically what we call 196 00:11:04,690 --> 00:11:07,810 a pre save hook. 197 00:11:07,810 --> 00:11:11,490 So you will see that terminology all the time. 198 00:11:11,490 --> 00:11:14,173 So some call it middleware, and some call it hooks. 199 00:11:15,270 --> 00:11:17,260 And so this is gonna be a pre save hook 200 00:11:17,260 --> 00:11:18,773 or pre save middleware. 201 00:11:21,880 --> 00:11:25,823 So function, and this one has access to next. 202 00:11:28,770 --> 00:11:31,433 And so let's just log something to the console here, 203 00:11:33,780 --> 00:11:37,963 like will save document. 204 00:11:40,740 --> 00:11:45,023 And then next, and that of course, should be next. 205 00:11:46,880 --> 00:11:48,750 Just to see if we get some error, 206 00:11:48,750 --> 00:11:50,653 I'm gonna omit the next here. 207 00:11:51,490 --> 00:11:55,283 Just to see what happens when we do not call it. 208 00:11:57,290 --> 00:11:59,080 So I'm gonna create a new tour, 209 00:11:59,080 --> 00:12:01,230 and by the end of this lecture I'm gonna delete 210 00:12:01,230 --> 00:12:04,543 all of them, but for now we need them here. 211 00:12:06,410 --> 00:12:09,930 And so now you see that it's not really finishing, 212 00:12:09,930 --> 00:12:12,620 so we're stuck in that one middleware function 213 00:12:12,620 --> 00:12:14,473 that doesn't have the next call. 214 00:12:16,410 --> 00:12:18,343 So basically we're stuck in here. 215 00:12:19,550 --> 00:12:20,970 So let's cancel the request 216 00:12:22,810 --> 00:12:25,780 and then get it back here, 217 00:12:25,780 --> 00:12:27,173 and try that again. 218 00:12:29,550 --> 00:12:32,070 And so now it worked indeed. 219 00:12:32,070 --> 00:12:35,740 So our slug is here, right, 220 00:12:35,740 --> 00:12:38,590 and so let's take a look at our console, 221 00:12:38,590 --> 00:12:41,973 and so indeed, our second pre middleware also run, 222 00:12:42,850 --> 00:12:45,797 so the one logging will save document and then 223 00:12:45,797 --> 00:12:49,320 our post middleware then logged to the console 224 00:12:49,320 --> 00:12:51,570 the final document, and so that should also 225 00:12:51,570 --> 00:12:55,043 already have the slug and yeah, here it is. 226 00:12:56,050 --> 00:12:57,870 And that's actually all I had to show you 227 00:12:57,870 --> 00:13:00,360 about document middleware. 228 00:13:00,360 --> 00:13:03,065 Now I'm just gonna comment out these two here 229 00:13:03,065 --> 00:13:06,680 because I don't want to pollute my log here 230 00:13:06,680 --> 00:13:09,110 all the time with these console.logs, 231 00:13:09,110 --> 00:13:11,190 but I'm still keeping them here, again, 232 00:13:11,190 --> 00:13:12,173 as a reference. 233 00:13:13,530 --> 00:13:16,330 So what I want you to remember from this lecture 234 00:13:16,330 --> 00:13:18,980 is that we can have middleware running before 235 00:13:18,980 --> 00:13:20,930 and after a certain event. 236 00:13:20,930 --> 00:13:23,160 And in the case of document middleware, 237 00:13:23,160 --> 00:13:25,850 that event is usually the save event. 238 00:13:25,850 --> 00:13:29,260 And then in the middleware function itself, 239 00:13:29,260 --> 00:13:31,660 we have access to the disk keyword, 240 00:13:31,660 --> 00:13:35,163 which is gonna point at the currently being saved document. 241 00:13:36,190 --> 00:13:38,232 And it's also very important to keep in mind 242 00:13:38,232 --> 00:13:42,650 that this save middleware only runs for the save 243 00:13:42,650 --> 00:13:44,650 and create Mongoose methods. 244 00:13:44,650 --> 00:13:47,690 It's not gonna run, for example, for insert many 245 00:13:47,690 --> 00:13:50,490 and also not for find one and update 246 00:13:50,490 --> 00:13:54,380 or find by ID and update, which we already used before. 247 00:13:54,380 --> 00:13:58,110 So for example, we somewhere here we have 248 00:14:00,870 --> 00:14:04,960 we have findByIdAndUpdate, but that is not gonna trigger 249 00:14:04,960 --> 00:14:06,862 this save middleware. 250 00:14:06,862 --> 00:14:09,610 So that's very important to keep in mind 251 00:14:09,610 --> 00:14:11,550 because actually a bit later in this project, 252 00:14:11,550 --> 00:14:14,950 we will have to work around that limitation. 253 00:14:14,950 --> 00:14:17,160 All right, so this is document middleware 254 00:14:17,160 --> 00:14:20,880 to manipulate documents that are currently being saved. 255 00:14:20,880 --> 00:14:23,833 Next up, we're gonna talk about query middleware.