1 00:00:01,110 --> 00:00:02,910 So, this is part two 2 00:00:02,910 --> 00:00:05,230 of calculating the review statistics. 3 00:00:05,230 --> 00:00:08,873 This time, for when a review is updated or deleted. 4 00:00:10,780 --> 00:00:13,310 And this part is actually a bit harder 5 00:00:13,310 --> 00:00:15,450 because, keep in mind that a review 6 00:00:15,450 --> 00:00:17,730 is updated or deleted using 7 00:00:19,829 --> 00:00:21,246 findByIdAndUpdate 8 00:00:25,490 --> 00:00:28,277 or also findByIdAndDelete, right? 9 00:00:33,540 --> 00:00:37,020 So for these, we actually do not have document middleware, 10 00:00:37,020 --> 00:00:39,830 but only query middleware, okay. 11 00:00:39,830 --> 00:00:42,630 And so in the query, we actually don't have direct access 12 00:00:42,630 --> 00:00:46,140 to the document in order to then do something similar 13 00:00:46,140 --> 00:00:48,300 to this, okay. 14 00:00:48,300 --> 00:00:51,380 Because, remember, we need access to the current review, 15 00:00:51,380 --> 00:00:54,130 so that from there, we can extract the tour ID, 16 00:00:54,130 --> 00:00:58,030 and then calculate the statistics from there, right, 17 00:00:58,030 --> 00:01:00,130 but again, for these hooks here, 18 00:01:00,130 --> 00:01:02,830 we only have query middleware, okay. 19 00:01:02,830 --> 00:01:04,890 But let me now show you a nice trick 20 00:01:04,890 --> 00:01:07,610 to actually go around this limitation. 21 00:01:07,610 --> 00:01:10,040 So, we're going to implement a pre-middleware 22 00:01:10,040 --> 00:01:14,073 for these hooks, for these events basically. 23 00:01:15,860 --> 00:01:19,730 So pre, and then again I'm going to use 24 00:01:19,730 --> 00:01:22,870 a regular expression for a string starting 25 00:01:22,870 --> 00:01:25,457 with findOneAnd and that's it. 26 00:01:28,641 --> 00:01:30,410 And so this one is then going to work 27 00:01:30,410 --> 00:01:33,970 for findOneAndUpdate, and findOneAndDelete 28 00:01:34,830 --> 00:01:37,150 because, remember that behind the scenes, 29 00:01:37,150 --> 00:01:40,480 findByIdAndUpdate is only just a shorthand 30 00:01:40,480 --> 00:01:44,750 for findOneAndUpdate with the current ID, right. 31 00:01:44,750 --> 00:01:48,530 So here, we actually need to use the findOneAndDelete 32 00:01:48,530 --> 00:01:52,833 and findOneAndUpdate middleware hooks, all right. 33 00:01:55,500 --> 00:01:59,970 So, function, and it gets the next keyword 34 00:01:59,970 --> 00:02:02,420 because it's pre-middleware. 35 00:02:02,420 --> 00:02:05,310 So, remember that the goal is to get access 36 00:02:05,310 --> 00:02:07,990 to the current review document, okay, 37 00:02:07,990 --> 00:02:11,280 but here the, this keyword is the current query. 38 00:02:11,280 --> 00:02:13,650 Now, how are we going to go around this? 39 00:02:13,650 --> 00:02:16,150 Well, we can basically execute a query, 40 00:02:16,150 --> 00:02:18,200 and then that will give us the document 41 00:02:18,200 --> 00:02:20,040 that's currently being processed. 42 00:02:20,040 --> 00:02:22,650 So in order to do that, we can use findOne. 43 00:02:25,590 --> 00:02:26,590 And that's it. 44 00:02:26,590 --> 00:02:29,740 So then all we need to do is await this query 45 00:02:29,740 --> 00:02:31,090 and then save it somewhere. 46 00:02:34,140 --> 00:02:38,850 So let's call it r, which is gonna stand for review, okay. 47 00:02:38,850 --> 00:02:40,763 Then save it as async. 48 00:02:42,650 --> 00:02:43,773 And, that's it. 49 00:02:45,000 --> 00:02:47,830 And just to make sure that this works here, 50 00:02:47,830 --> 00:02:52,340 let's for now just log this to the console, okay. 51 00:02:52,340 --> 00:02:55,080 So without doing any calculations, 52 00:02:55,080 --> 00:02:56,760 all we're really interested in 53 00:02:56,760 --> 00:02:59,960 is to see if this nice trick here works. 54 00:02:59,960 --> 00:03:02,410 So basically, the trick of going around 55 00:03:02,410 --> 00:03:04,070 that in a query midddleware, 56 00:03:04,070 --> 00:03:05,853 we only have access to the query. 57 00:03:06,890 --> 00:03:09,850 So again, we need to get access to the document, 58 00:03:09,850 --> 00:03:13,210 and so we basically execute this query 59 00:03:13,210 --> 00:03:14,463 by using findOne. 60 00:03:15,620 --> 00:03:20,603 All right, so let's update a review, 61 00:03:22,570 --> 00:03:26,313 and so let's actually update the last one that we did, 62 00:03:31,310 --> 00:03:33,050 all right, and the rating, 63 00:03:33,050 --> 00:03:35,010 now let's actually set it to four. 64 00:03:35,010 --> 00:03:37,080 So it was five before 65 00:03:38,130 --> 00:03:42,023 and so now we are changing it to four. 66 00:03:43,040 --> 00:03:44,083 So it sent that, 67 00:03:46,900 --> 00:03:50,620 and here is the review. 68 00:03:50,620 --> 00:03:53,140 Now of course, the rating is still set to five 69 00:03:53,140 --> 00:03:56,130 at this point, because this findOne here 70 00:03:56,130 --> 00:03:58,850 really gets the document from the database, 71 00:03:58,850 --> 00:04:01,660 and so at this point of time, in pre, 72 00:04:01,660 --> 00:04:04,900 it still didn't persist any changes to the database, 73 00:04:04,900 --> 00:04:06,540 and so it was five before, 74 00:04:06,540 --> 00:04:08,990 and so now it's still gonna be five. 75 00:04:08,990 --> 00:04:10,460 But that doesn't really matter here 76 00:04:10,460 --> 00:04:13,750 because all we are interested in is this ID. 77 00:04:13,750 --> 00:04:16,580 Actually, this tour ID, right, 78 00:04:16,580 --> 00:04:18,350 because that is what we're gonna need 79 00:04:18,350 --> 00:04:21,220 in order to calculate the average ratings. 80 00:04:21,220 --> 00:04:24,363 Okay, and so now, let's actually use that function. 81 00:04:25,240 --> 00:04:27,850 Okay, now, let's think about this 82 00:04:27,850 --> 00:04:32,190 because if we were to use this calcAverageRatings function 83 00:04:32,190 --> 00:04:33,850 at this point in time, 84 00:04:33,850 --> 00:04:36,100 then we would calculate the statistics 85 00:04:36,100 --> 00:04:39,490 using the non-updated data, okay. 86 00:04:39,490 --> 00:04:42,390 And so that's the exact same reason why up here, 87 00:04:42,390 --> 00:04:45,400 we also needed to use post and not pre, 88 00:04:45,400 --> 00:04:48,650 okay, because only after the document is already saved 89 00:04:48,650 --> 00:04:50,620 to the database it makes sense 90 00:04:50,620 --> 00:04:52,850 to then calculate the ratings. 91 00:04:52,850 --> 00:04:55,570 And so here, it's the exact same thing, 92 00:04:55,570 --> 00:04:58,650 with the big difference that we cannot simply change 93 00:04:58,650 --> 00:05:00,533 this pre to post. 94 00:05:01,390 --> 00:05:04,500 So we cannot do that because at this point in time 95 00:05:04,500 --> 00:05:07,260 we no longer have access to the query 96 00:05:07,260 --> 00:05:10,410 because the query has already executed, right, 97 00:05:10,410 --> 00:05:11,500 and so without the query, 98 00:05:11,500 --> 00:05:13,670 we cannot save the review document, 99 00:05:13,670 --> 00:05:16,410 and we can then not run this function. 100 00:05:16,410 --> 00:05:20,360 So, this is really confusing, I understand, 101 00:05:20,360 --> 00:05:23,710 but I really decided to create this lecture in this way 102 00:05:23,710 --> 00:05:25,790 because, well, it's really the only solution 103 00:05:25,790 --> 00:05:28,730 around this problem, and it's a really great exercise 104 00:05:28,730 --> 00:05:32,240 for you to basically understand this Hello Experience. 105 00:05:32,240 --> 00:05:35,833 So, the solution for this is to now use post, 106 00:05:37,520 --> 00:05:40,690 so, reviewSchema, then basically the same, 107 00:05:40,690 --> 00:05:44,460 so let's just, actually let's just copy all of this, 108 00:05:44,460 --> 00:05:47,640 make our lives a bit easier, 109 00:05:47,640 --> 00:05:50,033 get rid of this, and get rid of the next. 110 00:05:51,850 --> 00:05:54,320 Here, we also need to call next, okay, 111 00:05:54,320 --> 00:05:58,170 but then we do it post, okay. 112 00:05:58,170 --> 00:05:59,730 And so now this point in time, 113 00:05:59,730 --> 00:06:01,840 so after the query has already finished, 114 00:06:01,840 --> 00:06:04,700 and so therefore the review has been updated, 115 00:06:04,700 --> 00:06:06,290 this is a perfect point in time 116 00:06:06,290 --> 00:06:08,283 where we can then call this function. 117 00:06:09,510 --> 00:06:12,720 So, calculate average ratings. 118 00:06:12,720 --> 00:06:15,930 But where do we now get the tour ID from? 119 00:06:15,930 --> 00:06:17,860 Well, we're gonna have to use a trick 120 00:06:17,860 --> 00:06:21,260 which is basically to pass data from the pre-middleware 121 00:06:21,260 --> 00:06:23,000 to the post middleware. 122 00:06:23,000 --> 00:06:26,690 And so instead of saving this document to a simple variable, 123 00:06:26,690 --> 00:06:30,403 we're gonna save it to this.r. 124 00:06:31,750 --> 00:06:35,773 So basically, we create a property on this variable. 125 00:06:36,700 --> 00:06:40,390 Okay, and so now here, we still have access to that. 126 00:06:40,390 --> 00:06:45,350 And so now, we can say this.r, which remember is the review, 127 00:06:45,350 --> 00:06:47,603 and then .tour. 128 00:06:49,220 --> 00:06:53,300 So, this is again quite confusing, 129 00:06:53,300 --> 00:06:56,850 but again also quite fun once you understand 130 00:06:56,850 --> 00:06:58,873 how this really works, okay. 131 00:06:59,800 --> 00:07:03,200 Now, again, we need something like this here 132 00:07:03,200 --> 00:07:06,320 in order to actually call this function here 133 00:07:06,320 --> 00:07:08,460 because remember that this in fact 134 00:07:08,460 --> 00:07:12,570 is a static method, and so we need to call it on the model. 135 00:07:12,570 --> 00:07:15,500 Now where is this model in this case? 136 00:07:15,500 --> 00:07:20,500 Well, it's at this.r, 137 00:07:20,848 --> 00:07:22,550 which is in this case, equivalent 138 00:07:22,550 --> 00:07:25,113 to this this here in this middleware, 139 00:07:26,427 --> 00:07:29,217 .constructor.calcAverageRatings. 140 00:07:31,860 --> 00:07:35,403 Woo, that looks quite overwhelming, doesn't it? 141 00:07:36,600 --> 00:07:38,100 Of course, we have to await it, 142 00:07:38,100 --> 00:07:42,600 so that's why we declared this as async, okay. 143 00:07:42,600 --> 00:07:46,210 So, again, we basically used this way here 144 00:07:46,210 --> 00:07:48,530 of passing the data from the pre-middleware 145 00:07:48,530 --> 00:07:50,930 to the post middleware, and so then here 146 00:07:50,930 --> 00:07:55,060 we retrieved the review document from this variable. 147 00:07:55,060 --> 00:07:59,970 Okay, and again, we did have to do it in this way 148 00:07:59,970 --> 00:08:01,317 because at this point in time here, 149 00:08:01,317 --> 00:08:03,550 the query was already executed, 150 00:08:03,550 --> 00:08:06,783 and so we could not do this here. 151 00:08:11,950 --> 00:08:16,753 And let's actually write that down; does NOT work here, 152 00:08:19,690 --> 00:08:21,253 query has already executed. 153 00:08:22,610 --> 00:08:24,130 Great, and with this, 154 00:08:24,130 --> 00:08:27,103 we should actually now be ready to test this. 155 00:08:28,100 --> 00:08:32,850 So let's go ahead and update this one here once more, 156 00:08:32,850 --> 00:08:37,493 and set it to a rating of one, all right. 157 00:08:39,160 --> 00:08:41,060 Let's now let's take a look here, 158 00:08:41,060 --> 00:08:44,020 until you see that the number of ratings is still five, 159 00:08:44,020 --> 00:08:46,620 but the average is now only three, 160 00:08:46,620 --> 00:08:49,220 and now the question is if this really updated 161 00:08:49,220 --> 00:08:50,593 also on the tour, 162 00:08:53,740 --> 00:08:58,150 and, yep, indeed, it did. 163 00:08:58,150 --> 00:09:02,040 So, five ratings with an average of three. 164 00:09:02,040 --> 00:09:06,220 Great, let's now update another one. 165 00:09:06,220 --> 00:09:09,543 So, in order to that, let's get all our reviews, 166 00:09:11,570 --> 00:09:14,280 and actually we do not want all of them, 167 00:09:14,280 --> 00:09:16,201 but only the last one. 168 00:09:16,201 --> 00:09:18,730 And here I still I have this filter, 169 00:09:18,730 --> 00:09:20,253 so I should get rid of that, 170 00:09:21,650 --> 00:09:26,650 so we get all 65 results, so all of these reviews, 171 00:09:26,980 --> 00:09:29,280 but we only want the last ones, 172 00:09:29,280 --> 00:09:31,073 so the ones that we just created. 173 00:09:32,820 --> 00:09:34,160 So let's update... 174 00:09:37,570 --> 00:09:42,090 I'm not sure, because actually they're not in order here. 175 00:09:42,090 --> 00:09:47,090 Let's, okay, so here we have the most recent ones. 176 00:09:47,490 --> 00:09:50,963 So let me now update this one here, to let's say, four, 177 00:09:56,540 --> 00:09:59,410 just as a final test, and so that should 178 00:09:59,410 --> 00:10:01,173 bring the average up a little bit. 179 00:10:02,490 --> 00:10:04,090 And indeed it did. 180 00:10:04,090 --> 00:10:07,400 So, 3.6 now, and of course, the number is still five 181 00:10:07,400 --> 00:10:10,400 because you didn't add a new review. 182 00:10:10,400 --> 00:10:12,700 So it works great on update, 183 00:10:12,700 --> 00:10:15,463 let's now actually also test it with deleting. 184 00:10:17,470 --> 00:10:21,710 So let's go ahead and delete the review that we just updated 185 00:10:23,350 --> 00:10:26,860 and so now we should be down to only four, 186 00:10:26,860 --> 00:10:28,550 and indeed, here we are. 187 00:10:28,550 --> 00:10:30,100 So now, only four. 188 00:10:30,100 --> 00:10:32,053 And let's actually delete all of them. 189 00:10:35,410 --> 00:10:36,723 So, this one is next. 190 00:10:45,038 --> 00:10:46,180 Ah, here we are. 191 00:10:46,180 --> 00:10:47,303 Then also this one. 192 00:10:53,560 --> 00:10:55,760 So, now we should be down to three only 193 00:10:56,970 --> 00:11:00,350 or, actually, we only just have two left 194 00:11:00,350 --> 00:11:01,893 with an average of four. 195 00:11:05,600 --> 00:11:08,300 So let's see which one we have still left. 196 00:11:08,300 --> 00:11:12,330 So it's this one with three and this one with five. 197 00:11:12,330 --> 00:11:15,203 And so that's why we have this average of four. 198 00:11:19,210 --> 00:11:21,320 So let's get rid of this one 199 00:11:21,320 --> 00:11:25,020 and so now our average should be five, right? 200 00:11:25,020 --> 00:11:26,340 Or actually three 201 00:11:26,340 --> 00:11:29,340 because the only one that's left has three. 202 00:11:29,340 --> 00:11:33,350 And now the final test, deleting the last one, 203 00:11:33,350 --> 00:11:35,993 just to see what's gonna happen once we do that. 204 00:11:41,070 --> 00:11:42,530 And, we get an error here. 205 00:11:42,530 --> 00:11:46,400 So, cannot read property nRating of undefined. 206 00:11:46,400 --> 00:11:50,683 So that's calcAverageRatings at line number 69. 207 00:11:53,280 --> 00:11:54,903 So, don't know what this is. 208 00:11:55,760 --> 00:12:00,440 So, line 69, and so, it's this problem here. 209 00:12:00,440 --> 00:12:03,530 So we're trying to read nRating of undefined. 210 00:12:03,530 --> 00:12:06,420 So stats zero is basically undefined. 211 00:12:06,420 --> 00:12:09,400 And that's because if there are no document 212 00:12:09,400 --> 00:12:11,780 matching this query here basically, 213 00:12:11,780 --> 00:12:13,947 well then we simply get back an empty array. 214 00:12:13,947 --> 00:12:17,100 And so that's actually exactly what we have down here. 215 00:12:17,100 --> 00:12:19,350 So this is the stats array 216 00:12:19,350 --> 00:12:22,630 and so right now it doesn't have any results, okay, 217 00:12:22,630 --> 00:12:25,500 so we should only execute this piece of code here 218 00:12:25,500 --> 00:12:28,653 whenever we actually do have something in the stats array. 219 00:12:29,810 --> 00:12:30,903 So let's do that. 220 00:12:31,760 --> 00:12:36,760 So if stats.length is greater than zero, 221 00:12:40,090 --> 00:12:42,623 well, then do this. 222 00:12:45,450 --> 00:12:48,100 And if not, well, basically that means 223 00:12:48,100 --> 00:12:50,260 that all our reviews are gone, 224 00:12:50,260 --> 00:12:54,280 well then we basically want to go back to the default. 225 00:12:54,280 --> 00:12:58,780 So we're gonna set it then to the quantity of zero 226 00:12:58,780 --> 00:13:02,030 and the average of 4.5, which remember, 227 00:13:02,030 --> 00:13:04,943 is the default when there are no reviews at all. 228 00:13:08,540 --> 00:13:10,823 So let's quickly create a new review, 229 00:13:12,200 --> 00:13:13,150 and it can be this, 230 00:13:15,880 --> 00:13:19,400 all right, so we're back to having one rating, 231 00:13:19,400 --> 00:13:20,780 and now delete it right away, 232 00:13:20,780 --> 00:13:24,963 just to test that piece of code we just wrote, 233 00:13:28,080 --> 00:13:30,310 just to see it here as well, 234 00:13:30,310 --> 00:13:32,573 so one rating, average five. 235 00:13:33,850 --> 00:13:36,113 And now when we delete it, 236 00:13:38,910 --> 00:13:41,790 we no longer get an error. 237 00:13:41,790 --> 00:13:45,630 And on our tour, we are back to zero 238 00:13:45,630 --> 00:13:48,450 and a default of 4.5. 239 00:13:48,450 --> 00:13:51,560 All right, all right, all right, perfect. 240 00:13:51,560 --> 00:13:54,920 So let's again take just a quick second here 241 00:13:54,920 --> 00:13:57,090 to recap what we just did. 242 00:13:57,090 --> 00:13:59,970 So in order to be able to run this function here 243 00:13:59,970 --> 00:14:02,320 also on update and on delete, 244 00:14:02,320 --> 00:14:04,590 we actually need to use the query middleware 245 00:14:04,590 --> 00:14:07,110 that Mongoose gives us for these situations. 246 00:14:07,110 --> 00:14:11,230 Okay, so, we do not have a handy document middleware, 247 00:14:11,230 --> 00:14:13,140 which works, for these functions, 248 00:14:13,140 --> 00:14:15,880 but instead we need to use the query middleware, 249 00:14:15,880 --> 00:14:18,660 and in that one, we do not directly have access 250 00:14:18,660 --> 00:14:20,090 to the current document. 251 00:14:20,090 --> 00:14:21,540 And so we need to go around that 252 00:14:21,540 --> 00:14:24,870 by using this findOne here, and so basically retrieving 253 00:14:24,870 --> 00:14:27,340 the current document from the database. 254 00:14:27,340 --> 00:14:30,450 We then store it on the current query variable, 255 00:14:30,450 --> 00:14:32,950 and so that's this, and by doing that, 256 00:14:32,950 --> 00:14:36,480 we then get access to it in the post middleware. 257 00:14:36,480 --> 00:14:38,610 And it's then only in the post middleware 258 00:14:38,610 --> 00:14:42,500 where we actually calculate the statistics for reviews. 259 00:14:42,500 --> 00:14:44,370 And remember that we do it this way 260 00:14:44,370 --> 00:14:47,380 because if we did it right in this middleware function, 261 00:14:47,380 --> 00:14:50,100 then the underlying data would not have been updated 262 00:14:50,100 --> 00:14:53,150 at that point and so the calculated statistics 263 00:14:53,150 --> 00:14:55,150 would not really be up to date. 264 00:14:55,150 --> 00:14:56,540 And so that's why we used 265 00:14:56,540 --> 00:14:58,963 this two-step process here basically. 266 00:15:00,020 --> 00:15:02,220 Now, let's get rid of this console.log here, 267 00:15:03,130 --> 00:15:06,883 since we're finished now, and also of these statistics. 268 00:15:08,270 --> 00:15:11,390 So, I hope that this was fun to you 269 00:15:11,390 --> 00:15:13,890 and not all too overwhelming. 270 00:15:13,890 --> 00:15:16,390 I designed this exercise specifically 271 00:15:16,390 --> 00:15:19,270 so that we could solve a real world business problem 272 00:15:19,270 --> 00:15:22,150 by using all the tools that Mongoose gives us. 273 00:15:22,150 --> 00:15:24,500 And so, with that, I hope that you learned a bit better 274 00:15:24,500 --> 00:15:26,980 how to work with all these different middlewares 275 00:15:26,980 --> 00:15:29,220 in different situations whenever needed 276 00:15:29,220 --> 00:15:31,640 in a real world situation. 277 00:15:31,640 --> 00:15:35,700 So, great job for finishing this quite challenging lecture 278 00:15:35,700 --> 00:15:39,030 and for still being with me at this point of the course. 279 00:15:39,030 --> 00:15:40,594 It's really good for me to see, 280 00:15:40,594 --> 00:15:43,500 so I'm really happy about that. 281 00:15:43,500 --> 00:15:46,780 But anyway, there's still some more great content coming up 282 00:15:46,780 --> 00:15:48,290 in this section actually, 283 00:15:48,290 --> 00:15:51,723 and so let's now move on together, right to the next video.