1 00:00:01,150 --> 00:00:04,333 Next up, let's talk about custom validators. 2 00:00:05,940 --> 00:00:10,110 So sometimes the built-in validators are simply not enough. 3 00:00:10,110 --> 00:00:11,100 And in that case, 4 00:00:11,100 --> 00:00:14,250 we can also build our own custom validators. 5 00:00:14,250 --> 00:00:18,230 And a validator is actually really just a simple function 6 00:00:18,230 --> 00:00:21,250 which should return either true or false. 7 00:00:21,250 --> 00:00:24,330 And if it returns false, then it means there is an error. 8 00:00:24,330 --> 00:00:26,650 And on the other hand when we return true, 9 00:00:26,650 --> 00:00:28,690 then the validation is correct 10 00:00:28,690 --> 00:00:31,260 and the input can be accepted. 11 00:00:31,260 --> 00:00:35,560 Okay, so let's now build a simple custom validator here. 12 00:00:35,560 --> 00:00:39,980 And what I want to validate is if the price discount 13 00:00:39,980 --> 00:00:42,863 is actually lower than the price itself. 14 00:00:44,440 --> 00:00:46,130 That's something that we cannot do 15 00:00:46,130 --> 00:00:47,980 using the built-in validators 16 00:00:47,980 --> 00:00:49,980 and so we're simply gonna build our own. 17 00:00:52,575 --> 00:00:54,690 We need to now specify here an object 18 00:00:54,690 --> 00:00:56,453 for the SchemaType options. 19 00:01:00,170 --> 00:01:01,003 Alright. 20 00:01:05,190 --> 00:01:07,400 So the type is number, 21 00:01:07,400 --> 00:01:09,880 and then to specify our validator 22 00:01:09,880 --> 00:01:11,853 we use the validate property. 23 00:01:15,270 --> 00:01:17,580 Validate, and then as I said, 24 00:01:17,580 --> 00:01:19,173 a simple callback function. 25 00:01:21,600 --> 00:01:23,840 And again, not an arrow function, 26 00:01:23,840 --> 00:01:25,090 but a real function, 27 00:01:25,090 --> 00:01:26,200 because in this function 28 00:01:26,200 --> 00:01:28,730 we're gonna have access to the this variable, 29 00:01:28,730 --> 00:01:30,983 which will point to the current document. 30 00:01:31,940 --> 00:01:34,540 Now if you didn't need the this variable, 31 00:01:34,540 --> 00:01:37,140 then you could of course just use an arrow function. 32 00:01:39,710 --> 00:01:41,150 We have a callback function, 33 00:01:41,150 --> 00:01:43,910 and that callback function actually has access 34 00:01:43,910 --> 00:01:46,180 to the value that was inputted. 35 00:01:46,180 --> 00:01:50,330 So in this case, the price discount that the user specified. 36 00:01:50,330 --> 00:01:53,773 So that's what I call the value, val for short. 37 00:01:55,340 --> 00:01:57,550 Remember that we need to return either 38 00:01:57,550 --> 00:01:59,873 true or false from this validator. 39 00:02:04,090 --> 00:02:05,760 When do we want to return false, 40 00:02:05,760 --> 00:02:08,230 and when do we want to return true? 41 00:02:08,230 --> 00:02:11,210 Well, we want an error when the price discount 42 00:02:11,210 --> 00:02:13,553 is greater or equal than the price. 43 00:02:14,430 --> 00:02:17,000 And so basically what we want to return here 44 00:02:17,000 --> 00:02:19,800 is the test of testing 45 00:02:19,800 --> 00:02:23,493 if the value is less than this.price. 46 00:02:26,050 --> 00:02:30,210 All right, so let's say that the price discount 47 00:02:30,210 --> 00:02:33,693 is 100 and that the real price is 200. 48 00:02:35,090 --> 00:02:39,080 100 is less than 200, true and so we have no error. 49 00:02:39,080 --> 00:02:42,110 And that makes sense because that's exactly what we want. 50 00:02:42,110 --> 00:02:44,990 The price discount should always be lower. 51 00:02:44,990 --> 00:02:49,000 On the other hand, if the discount is 250, 52 00:02:49,000 --> 00:02:50,970 then this turns out to be false. 53 00:02:50,970 --> 00:02:54,623 And then false, remember, will trigger a validation error. 54 00:02:57,980 --> 00:02:59,530 Let's now test it out actually. 55 00:03:01,890 --> 00:03:02,723 Price 56 00:03:03,877 --> 00:03:06,800 (keyboard clacking) 57 00:03:06,800 --> 00:03:07,973 and price discount. 58 00:03:09,220 --> 00:03:12,000 And let's use the values that we used before 59 00:03:13,870 --> 00:03:17,133 and I also need to change the name here. 60 00:03:18,660 --> 00:03:22,990 Okay, so right now our discount is greater than the price 61 00:03:22,990 --> 00:03:24,833 and so we should get our error. 62 00:03:26,440 --> 00:03:30,560 Okay and indeed, we have a validation error. 63 00:03:30,560 --> 00:03:33,850 So failed for path price discount. 64 00:03:33,850 --> 00:03:37,020 Now, we do not have any custom message here 65 00:03:37,020 --> 00:03:39,113 and so let's quickly fix that. 66 00:03:40,230 --> 00:03:43,580 All right and the way we do that is in a very similar way 67 00:03:43,580 --> 00:03:45,650 as we did with the enum. 68 00:03:47,750 --> 00:03:50,510 So we need to actually specify another object 69 00:03:50,510 --> 00:03:52,313 and then set the message property. 70 00:03:55,830 --> 00:03:56,663 Validate 71 00:03:59,320 --> 00:04:00,940 should be an object 72 00:04:00,940 --> 00:04:03,280 and then we have our message in there 73 00:04:04,370 --> 00:04:06,510 and this function here will live 74 00:04:06,510 --> 00:04:08,597 in a property called validator. 75 00:04:15,639 --> 00:04:18,205 Okay and our message here will be 76 00:04:18,205 --> 00:04:21,527 (keyboard clacking) 77 00:04:21,527 --> 00:04:22,360 discount price 78 00:04:23,510 --> 00:04:24,343 should be 79 00:04:26,220 --> 00:04:27,693 below the regular price. 80 00:04:30,520 --> 00:04:34,840 Here we need a comma and so now we're good. 81 00:04:34,840 --> 00:04:38,480 And actually, one very nice trick is that this message here 82 00:04:38,480 --> 00:04:41,003 also has access to the value. 83 00:04:42,180 --> 00:04:44,930 And this works in kind of a weird way 84 00:04:44,930 --> 00:04:47,520 and this really is internal to Mongoose, 85 00:04:47,520 --> 00:04:49,610 so this has nothing to do with JavaScript 86 00:04:49,610 --> 00:04:54,283 so I can simply use the curly braces here and then value. 87 00:04:56,030 --> 00:04:58,020 So this piece here will get access 88 00:04:58,020 --> 00:04:59,900 to the value that was inputted, 89 00:04:59,900 --> 00:05:02,973 so it has the exact same value as this val variable. 90 00:05:06,150 --> 00:05:07,400 So let's test that again 91 00:05:08,720 --> 00:05:10,850 and now indeed we get our message 92 00:05:10,850 --> 00:05:15,800 and even access to the 250 price that we specified here. 93 00:05:15,800 --> 00:05:19,890 Now let's change it to 100 and so now it should work 94 00:05:19,890 --> 00:05:21,920 and yeah, it does. 95 00:05:21,920 --> 00:05:23,570 So, great. 96 00:05:23,570 --> 00:05:26,290 Now there is one very important caveat 97 00:05:26,290 --> 00:05:28,030 that we need to notice here 98 00:05:28,030 --> 00:05:30,763 and that is that inside a validator function, 99 00:05:30,763 --> 00:05:33,080 that this key word is only gonna point 100 00:05:33,080 --> 00:05:34,290 to the current document 101 00:05:34,290 --> 00:05:36,573 when we are creating a new document. 102 00:05:37,740 --> 00:05:40,653 So this function here is not going to work on update. 103 00:05:41,813 --> 00:05:44,143 And so that's very important to note. 104 00:05:45,412 --> 00:05:48,230 You see, that in Mongoose, there are a couple of caveats 105 00:05:48,230 --> 00:05:50,110 that you really need to be aware of 106 00:05:50,110 --> 00:05:51,990 when working with it. 107 00:05:51,990 --> 00:05:54,430 And I learned all of these by experience 108 00:05:54,430 --> 00:05:57,390 and so that's why now I'm able to tell them to you. 109 00:05:57,390 --> 00:06:00,550 So I run into an error once with this one 110 00:06:00,550 --> 00:06:02,090 and so from that time on, 111 00:06:02,090 --> 00:06:05,220 I know that I can only use this kind of validator 112 00:06:05,220 --> 00:06:07,160 with a this keyword in there 113 00:06:07,160 --> 00:06:09,730 when I'm actually creating new documents. 114 00:06:09,730 --> 00:06:12,143 So let me write that down here for you. 115 00:06:12,143 --> 00:06:15,143 (keyboard clacking) 116 00:06:25,210 --> 00:06:28,610 All right, so I hope that you're kind of taking note 117 00:06:28,610 --> 00:06:32,440 of all of these very important small pieces of information 118 00:06:32,440 --> 00:06:34,083 that are very important. 119 00:06:34,940 --> 00:06:36,680 The same thing down here. 120 00:06:36,680 --> 00:06:38,530 Remember that where I told you that 121 00:06:38,530 --> 00:06:42,100 this DOCUMENT MIDDLEWARE only really runs for save 122 00:06:42,100 --> 00:06:44,640 and create but not for update. 123 00:06:44,640 --> 00:06:46,700 And that's one of these other things 124 00:06:46,700 --> 00:06:49,013 that are really important to never forget. 125 00:06:51,330 --> 00:06:52,860 Now in this specific case here, 126 00:06:52,860 --> 00:06:55,870 there are actually ways around fixing this 127 00:06:55,870 --> 00:06:58,903 but they're very complicated and not really worth pursuing. 128 00:07:00,070 --> 00:07:02,810 And we could of course also write validator functions 129 00:07:02,810 --> 00:07:05,370 that do not rely on a this variable. 130 00:07:05,370 --> 00:07:08,000 So in this case, we only need it because we are comparing 131 00:07:08,000 --> 00:07:11,363 one value with the value of another field. 132 00:07:14,150 --> 00:07:17,370 This is a custom validator that we can use in Mongoose 133 00:07:17,370 --> 00:07:20,180 and that we did actually write ourself. 134 00:07:20,180 --> 00:07:23,170 But also, there are a couple of libraries on npm 135 00:07:23,170 --> 00:07:26,300 for data validation that we can simply plug in here 136 00:07:26,300 --> 00:07:30,183 as custom validators that we do not have to write ourselves. 137 00:07:31,394 --> 00:07:34,370 And the most popular library is called validator 138 00:07:34,370 --> 00:07:36,883 and so let's actually take a look at that one. 139 00:07:41,490 --> 00:07:44,520 Validator and then I'm searching for GitHub 140 00:07:44,520 --> 00:07:48,620 because usually all of these libraries are always on GitHub. 141 00:07:48,620 --> 00:07:51,300 And the documentation is also gonna be there 142 00:07:52,210 --> 00:07:53,660 and so here you see 143 00:07:55,060 --> 00:07:56,330 that validator 144 00:07:56,330 --> 00:07:59,773 is a library of string validators and sanitizers. 145 00:08:01,155 --> 00:08:05,310 You also see that it's quite popular with 13,00 stars 146 00:08:05,310 --> 00:08:06,500 and so 147 00:08:06,500 --> 00:08:08,033 that's very good. 148 00:08:09,880 --> 00:08:11,830 We also see this library validates 149 00:08:11,830 --> 00:08:13,683 and sanitize only strings. 150 00:08:15,562 --> 00:08:18,280 Here is then all of the stuff how we install it 151 00:08:18,280 --> 00:08:21,070 and how we use it but that's kind of simple. 152 00:08:21,070 --> 00:08:22,655 We already know that. 153 00:08:22,655 --> 00:08:24,650 But what I want to show you is the list 154 00:08:24,650 --> 00:08:26,990 of all the available validators. 155 00:08:26,990 --> 00:08:29,490 For example, we have isAlpha, 156 00:08:29,490 --> 00:08:32,900 which is gonna check if the string contains only letters. 157 00:08:32,900 --> 00:08:36,140 We have Alphanumeric so only letters and numbers 158 00:08:36,980 --> 00:08:38,910 and we really have a lot of stuff here. 159 00:08:38,910 --> 00:08:40,820 So check if a string is boolian, 160 00:08:40,820 --> 00:08:43,870 or check if the string is a credit card, 161 00:08:43,870 --> 00:08:46,160 so valid credit card number. 162 00:08:46,160 --> 00:08:48,700 Or if it's a currency 163 00:08:48,700 --> 00:08:52,860 or you see really all kinds of different tests. 164 00:08:52,860 --> 00:08:56,783 For example an ISBN, so for checking book numbers. 165 00:08:59,020 --> 00:09:02,683 To test if it's an integer or if the string is lowercase. 166 00:09:03,740 --> 00:09:07,050 And so you see, whenever you need some data validation 167 00:09:07,050 --> 00:09:08,970 you can grab one of these libraries 168 00:09:08,970 --> 00:09:11,993 and simply plug them into your Mongoose validators. 169 00:09:13,650 --> 00:09:15,560 Now many of the things that are here 170 00:09:15,560 --> 00:09:17,800 are actually already built into Mongoose 171 00:09:17,800 --> 00:09:20,810 and so we don't need all of them, okay, 172 00:09:20,810 --> 00:09:23,010 but there is one very specific, 173 00:09:23,010 --> 00:09:25,880 which I want to use, which is isAlpha. 174 00:09:25,880 --> 00:09:30,290 So I want to check if the tour name only contains letters. 175 00:09:30,290 --> 00:09:32,200 And so for that I can use this function 176 00:09:32,200 --> 00:09:33,963 from the validator library. 177 00:09:35,940 --> 00:09:36,773 Let's go back 178 00:09:38,804 --> 00:09:40,000 and start by installing 179 00:09:41,660 --> 00:09:42,493 npm 180 00:09:42,493 --> 00:09:43,877 i 181 00:09:43,877 --> 00:09:45,270 (keyboard clacking) 182 00:09:45,270 --> 00:09:46,163 validator. 183 00:09:52,614 --> 00:09:53,793 That was successful. 184 00:09:56,481 --> 00:09:57,931 Then I need to import it here 185 00:10:01,430 --> 00:10:05,363 and so now we're good to go to actually use it here. 186 00:10:07,380 --> 00:10:08,530 I'm gonna use it here 187 00:10:08,530 --> 00:10:10,790 and again, I use the validate property 188 00:10:12,510 --> 00:10:13,900 and now all I need to do 189 00:10:13,900 --> 00:10:16,253 is to really plug in the function here. 190 00:10:18,470 --> 00:10:21,350 And in validator, it works like this, 191 00:10:21,350 --> 00:10:23,530 where validator is an object 192 00:10:23,530 --> 00:10:26,330 and on there we have then all these methods. 193 00:10:26,330 --> 00:10:27,560 Validator 194 00:10:27,560 --> 00:10:28,393 is 195 00:10:30,240 --> 00:10:31,073 Alpha, 196 00:10:31,073 --> 00:10:32,490 so that's the one that we just choose 197 00:10:32,490 --> 00:10:33,783 from the documentation. 198 00:10:34,936 --> 00:10:36,090 And that's actually it. 199 00:10:36,090 --> 00:10:37,760 So we don't call it here. 200 00:10:37,760 --> 00:10:39,900 We basically just specify 201 00:10:39,900 --> 00:10:42,780 that this is a function that should be used. 202 00:10:42,780 --> 00:10:45,920 Just like our own one, like our own validator, 203 00:10:45,920 --> 00:10:46,830 we didn't call it. 204 00:10:46,830 --> 00:10:48,870 We simply put this callback function here 205 00:10:48,870 --> 00:10:49,970 that it's gonna be called 206 00:10:49,970 --> 00:10:52,153 as soon as the data should be validated. 207 00:10:54,527 --> 00:10:56,090 And so here, it's the same. 208 00:10:56,090 --> 00:10:58,490 Now, if we wanna specify an error message, 209 00:10:58,490 --> 00:11:00,550 it works just like up here. 210 00:11:00,550 --> 00:11:04,180 We can specify an array and then the error message 211 00:11:04,180 --> 00:11:05,850 after the callback function. 212 00:11:05,850 --> 00:11:07,883 And we could have done it down here. 213 00:11:09,120 --> 00:11:11,000 So here we did it differently. 214 00:11:11,000 --> 00:11:13,230 Here we then created this new object 215 00:11:13,230 --> 00:11:16,010 with validator in there and the message, 216 00:11:16,010 --> 00:11:18,220 but we could've done it with an array as well, 217 00:11:18,220 --> 00:11:20,183 but that would've looked weird. 218 00:11:21,130 --> 00:11:23,830 But up here, since the function is so small, 219 00:11:23,830 --> 00:11:26,540 so this is so small, we can simply put it here 220 00:11:26,540 --> 00:11:29,040 and then as a second argument in the array 221 00:11:29,040 --> 00:11:30,463 add the error message. 222 00:11:32,640 --> 00:11:35,110 Tour name must only contain 223 00:11:35,973 --> 00:11:39,310 (keyboard clacking) characters. 224 00:11:39,310 --> 00:11:41,053 Great, check that out. 225 00:11:42,320 --> 00:11:47,053 Back in Postman here, let's get rid of our price discount. 226 00:11:48,990 --> 00:11:51,290 And let's add some number here. 227 00:11:51,290 --> 00:11:53,140 And so that should then fail the test 228 00:11:54,450 --> 00:11:57,433 and indeed, the name must only contain characters. 229 00:11:59,760 --> 00:12:01,430 Let's get rid of that. 230 00:12:01,430 --> 00:12:02,760 We can also not use this name. 231 00:12:02,760 --> 00:12:05,040 We already used it before, 232 00:12:05,040 --> 00:12:08,500 so that can be write out too here with characters 233 00:12:10,060 --> 00:12:13,503 and we still get this error here. 234 00:12:15,470 --> 00:12:18,830 Well, that's probably because of the spaces. 235 00:12:18,830 --> 00:12:20,970 So let's just get rid of the spaces, 236 00:12:20,970 --> 00:12:23,900 which of course is not gonna be real useful 237 00:12:23,900 --> 00:12:25,910 and indeed, now it works. 238 00:12:25,910 --> 00:12:27,900 So the problem was the spaces, 239 00:12:27,900 --> 00:12:30,483 but obviously we want to keep the spaces here. 240 00:12:32,650 --> 00:12:36,400 In fact, this validation error is not really useful 241 00:12:36,400 --> 00:12:37,993 and so I will get rid of it. 242 00:12:39,340 --> 00:12:42,430 Consider that this here was only to demonstrate 243 00:12:42,430 --> 00:12:45,030 that we can use an external library like this 244 00:12:45,030 --> 00:12:46,880 to perform validation. 245 00:12:46,880 --> 00:12:49,670 And actually, we will still use this library a bit later 246 00:12:49,670 --> 00:12:53,390 when we check if the user email is actually valid. 247 00:12:53,390 --> 00:12:54,860 So that's another nice function 248 00:12:54,860 --> 00:12:56,873 that is included in this library. 249 00:12:58,788 --> 00:13:00,290 So again, this is how it works. 250 00:13:00,290 --> 00:13:02,270 Not really useful in this case, 251 00:13:02,270 --> 00:13:04,050 so if we really wanted to test 252 00:13:04,050 --> 00:13:08,160 if the string only contains letters and spaces 253 00:13:08,160 --> 00:13:09,700 it would probably be simpler 254 00:13:09,700 --> 00:13:12,250 to simply use a regular expression 255 00:13:12,250 --> 00:13:14,153 to test for that kind of pattern. 256 00:13:15,210 --> 00:13:16,500 But I'm not gonna do that here 257 00:13:16,500 --> 00:13:18,410 because this lecture was more about 258 00:13:18,410 --> 00:13:20,230 these custom validators. 259 00:13:20,230 --> 00:13:23,810 Anyway, with this lecture, we are now ready 260 00:13:23,810 --> 00:13:25,863 with the introduction to Mongoose. 261 00:13:27,370 --> 00:13:29,500 Now as you can imagine, there is of course 262 00:13:29,500 --> 00:13:31,530 still a lot to learn about Mongoose 263 00:13:31,530 --> 00:13:34,540 and in fact, we have a advanced Mongoose section 264 00:13:34,540 --> 00:13:36,010 a bit later in the course 265 00:13:36,010 --> 00:13:38,010 and of course also in the other sections, 266 00:13:38,010 --> 00:13:39,710 you will keep learning more and more 267 00:13:39,710 --> 00:13:41,390 about how to use Mongoose 268 00:13:41,390 --> 00:13:43,183 in a real professional way. 269 00:13:44,380 --> 00:13:47,070 You have already learned so much up until this point, 270 00:13:47,070 --> 00:13:50,630 so huge congratulations for making it this far 271 00:13:50,630 --> 00:13:53,680 and it's great to see that you're still with me here. 272 00:13:53,680 --> 00:13:56,913 So great job and I hope to see you soon.