1 00:00:01,210 --> 00:00:02,660 So far in this section, 2 00:00:02,660 --> 00:00:04,860 we have talked about Mongoose models, 3 00:00:04,860 --> 00:00:06,940 CRUD operations with Mongoose, 4 00:00:06,940 --> 00:00:09,660 we did a lot of querying, and we learned about 5 00:00:09,660 --> 00:00:12,820 the aggregation pipeline, but now for the next 6 00:00:12,820 --> 00:00:15,110 couple of videos, let's actually return 7 00:00:15,110 --> 00:00:18,860 to our data model and learn some super useful features 8 00:00:18,860 --> 00:00:22,170 that Mongoose offers us in order to model our data. 9 00:00:22,170 --> 00:00:24,090 And the first one we're gonna talk about 10 00:00:24,090 --> 00:00:25,773 are virtual properties. 11 00:00:27,410 --> 00:00:29,973 And so let's open our tour model here. 12 00:00:31,050 --> 00:00:35,080 All right, now virtual properties are basically fields 13 00:00:35,080 --> 00:00:37,030 that we can define on our schema 14 00:00:37,030 --> 00:00:39,150 but that will not be persisted. 15 00:00:39,150 --> 00:00:42,100 So they will not be saved into the database 16 00:00:42,100 --> 00:00:44,720 in order to save us some space there. 17 00:00:44,720 --> 00:00:46,140 And most of the time, of course, 18 00:00:46,140 --> 00:00:49,260 we want to really save our data to the database, 19 00:00:49,260 --> 00:00:51,700 but virtual properties make a lot of sense 20 00:00:51,700 --> 00:00:55,090 for fields that can be derived from one another. 21 00:00:55,090 --> 00:00:58,410 For example a conversion from miles to kilometers, 22 00:00:58,410 --> 00:01:00,720 it doesn't make sense to store these two fields 23 00:01:00,720 --> 00:01:03,260 in a database if we can easily convert 24 00:01:03,260 --> 00:01:05,750 one to the other, right? 25 00:01:05,750 --> 00:01:09,140 Okay, so let's now define a virtual property 26 00:01:09,140 --> 00:01:11,680 that contains the tour duration in weeks. 27 00:01:11,680 --> 00:01:13,800 And so that's a field basically 28 00:01:13,800 --> 00:01:16,460 that we can very easily convert from the duration 29 00:01:16,460 --> 00:01:18,970 that we already have in days, right? 30 00:01:18,970 --> 00:01:20,523 And so here is how it works. 31 00:01:22,160 --> 00:01:25,640 We define that virtual properties on the tour schema, 32 00:01:25,640 --> 00:01:30,640 and so we say, tourSchema.virtual and then the name 33 00:01:33,430 --> 00:01:34,763 of the virtual property. 34 00:01:36,530 --> 00:01:39,300 So let's call it duration weeks, 35 00:01:39,300 --> 00:01:42,950 and then on there we need to define the get method. 36 00:01:42,950 --> 00:01:45,600 And that's just because this virtual property here 37 00:01:45,600 --> 00:01:47,580 will basically be created each time 38 00:01:47,580 --> 00:01:50,560 that we get some data out of the database. 39 00:01:50,560 --> 00:01:54,273 And so this get function here is called a getter. 40 00:01:54,273 --> 00:01:57,090 Now in here we pass a function, 41 00:01:57,090 --> 00:01:58,400 and actually this call back function 42 00:01:58,400 --> 00:02:02,460 is gonna be a real function, so not an arrow function, 43 00:02:02,460 --> 00:02:05,672 and I'm gonna explain to you why in a second. 44 00:02:05,672 --> 00:02:08,500 Now how do we then basically define 45 00:02:08,500 --> 00:02:10,810 the virtual property? 46 00:02:10,810 --> 00:02:13,420 Well it's very simple, all we have to say 47 00:02:13,420 --> 00:02:18,280 is that we want to return this, .duration in this case, 48 00:02:18,280 --> 00:02:19,833 divided by seven. 49 00:02:21,020 --> 00:02:24,350 So this is how we calculate the duration in weeks, 50 00:02:24,350 --> 00:02:26,730 so the duration in days divided by seven 51 00:02:26,730 --> 00:02:29,110 because there are seven days in the week, 52 00:02:29,110 --> 00:02:31,030 and so that's then the duration in weeks. 53 00:02:31,030 --> 00:02:33,510 For example, if a tour has seven days, 54 00:02:33,510 --> 00:02:35,730 then it's of course gonna be one week. 55 00:02:35,730 --> 00:02:38,360 Now I used this regular function here 56 00:02:38,360 --> 00:02:41,250 because remember, an arrow function does not get 57 00:02:41,250 --> 00:02:43,060 its own disk keyword. 58 00:02:43,060 --> 00:02:45,800 In here we actually need the disk keyword 59 00:02:45,800 --> 00:02:48,470 because the disk keyword in this case 60 00:02:48,470 --> 00:02:51,588 is going to be pointing to the current document. 61 00:02:51,588 --> 00:02:54,640 And so usually when we want to use this, 62 00:02:54,640 --> 00:02:58,714 then we should always use a regular function. 63 00:02:58,714 --> 00:03:01,140 So really everywhere in Mongoose, 64 00:03:01,140 --> 00:03:04,340 I'm gonna always be using these regular functions 65 00:03:04,340 --> 00:03:06,061 that we're used to. 66 00:03:06,061 --> 00:03:11,061 So give it a save here, and that's actually it. 67 00:03:11,070 --> 00:03:13,180 That's how we define duration weeks, 68 00:03:13,180 --> 00:03:15,660 which is not going to be persisted in the database, 69 00:03:15,660 --> 00:03:19,150 but it's only gonna be there as soon as we get the data. 70 00:03:19,150 --> 00:03:21,820 Now right now it's actually not gonna be there yet, 71 00:03:21,820 --> 00:03:24,610 because there's one piece missing here, 72 00:03:24,610 --> 00:03:27,243 so let me start by showing you that. 73 00:03:28,760 --> 00:03:31,240 So if we try to get all tours, 74 00:03:31,240 --> 00:03:34,050 you will see that duration weeks is nowhere 75 00:03:34,050 --> 00:03:35,768 to be found here. 76 00:03:35,768 --> 00:03:38,660 And that's because we need to explicitly define 77 00:03:38,660 --> 00:03:41,740 in our schema that we want the virtual properties 78 00:03:41,740 --> 00:03:42,683 in our output. 79 00:03:43,758 --> 00:03:48,758 And so remember how I said that into this Mongoose.schema, 80 00:03:49,320 --> 00:03:51,650 we can pass in not only the object 81 00:03:51,650 --> 00:03:54,050 with the schema definition itself, 82 00:03:54,050 --> 00:03:56,943 but also an object for the schema options. 83 00:03:58,070 --> 00:04:00,579 And so let's add that here at the end, 84 00:04:00,579 --> 00:04:04,810 so this first object here is the schema definition, 85 00:04:04,810 --> 00:04:07,630 and now second an object for the options. 86 00:04:07,630 --> 00:04:11,260 And what we need to specify here is the two JSON 87 00:04:12,390 --> 00:04:15,410 property here, and what we say is then 88 00:04:15,410 --> 00:04:19,453 that each time that the data is actually outputted as JSON, 89 00:04:20,480 --> 00:04:22,710 we want virtuals to be true. 90 00:04:23,681 --> 00:04:26,657 So basically the virtuals to be part of the output. 91 00:04:27,800 --> 00:04:30,000 And now I'm duplicating this because we also 92 00:04:30,000 --> 00:04:31,923 want to say to object. 93 00:04:33,370 --> 00:04:36,037 So basically when the data gets outputted 94 00:04:36,037 --> 00:04:37,320 as an object. 95 00:04:37,320 --> 00:04:40,010 And so if we now go back here, we should then 96 00:04:40,010 --> 00:04:41,993 be able to see duration weeks. 97 00:04:43,120 --> 00:04:46,550 Let's wait for it, and indeed, here it is. 98 00:04:46,550 --> 00:04:51,053 So it's five days, and so that is 0.71 weeks. 99 00:04:52,250 --> 00:04:55,800 Here we have seven days, and so that's one week. 100 00:04:55,800 --> 00:04:59,810 Okay, so that actually works, great. 101 00:04:59,810 --> 00:05:01,680 Now one thing that we need to keep in mind 102 00:05:01,680 --> 00:05:04,840 is that we cannot use this virtual property here 103 00:05:04,840 --> 00:05:07,840 in a query, because they're technically 104 00:05:07,840 --> 00:05:09,980 not part of the database. 105 00:05:09,980 --> 00:05:11,370 So we can not say, for example, 106 00:05:11,370 --> 00:05:16,370 tour.find where duration weeks is equal to one. 107 00:05:16,618 --> 00:05:19,660 That's not gonna work, again because this property 108 00:05:19,660 --> 00:05:22,520 is not actually part of the database. 109 00:05:22,520 --> 00:05:25,330 Now of course we could also have done this conversion 110 00:05:25,330 --> 00:05:28,450 each time after we query the data, for example, 111 00:05:28,450 --> 00:05:30,890 like in a controller, but that would not 112 00:05:30,890 --> 00:05:34,240 be the best practice simply because we want to try 113 00:05:34,240 --> 00:05:36,960 to keep business logic and application logic 114 00:05:36,960 --> 00:05:39,830 as much separated as possible, remember? 115 00:05:39,830 --> 00:05:42,980 So that was that whole talk about fat models 116 00:05:42,980 --> 00:05:46,950 and thin controllers that we talked about before 117 00:05:46,950 --> 00:05:48,850 which says that we should have models 118 00:05:48,850 --> 00:05:52,390 with as much business logic as we can offload to them 119 00:05:52,390 --> 00:05:54,460 and thin controllers with as little 120 00:05:54,460 --> 00:05:56,598 business logic as possible. 121 00:05:56,598 --> 00:05:59,840 And so virtual properties like this are actually 122 00:05:59,840 --> 00:06:01,970 a good example of how we can achieve 123 00:06:01,970 --> 00:06:03,483 that kind of architecture. 124 00:06:04,410 --> 00:06:06,460 So knowing the duration in weeks 125 00:06:06,460 --> 00:06:09,070 is a business logic because it has to do 126 00:06:09,070 --> 00:06:11,900 with the business itself, not with stuff like requests 127 00:06:11,900 --> 00:06:14,550 or responses, and so we do the calculation 128 00:06:14,550 --> 00:06:16,460 right in the model where it belongs 129 00:06:16,460 --> 00:06:17,863 and not in the controller.