Instructor: So far in this section,
we have talked about Mongoose models,
CRUD operations with Mongoose,
we did a lot of querying, and we learned about
the aggregation pipeline, but now for the next
couple of videos, let's actually return
to our data model and learn some super useful features
that Mongoose offers us in order to model our data.
And the first one we're gonna talk about
are virtual properties.
And so let's open our tour model here.
All right, now virtual properties are basically fields
that we can define on our schema
but that will not be persisted.
So they will not be saved into the database
in order to save us some space there.
And most of the time, of course,
we want to really save our data to the database,
but virtual properties make a lot of sense
for fields that can be derived from one another.
For example a conversion from miles to kilometers,
it doesn't make sense to store these two fields
in a database if we can easily convert
one to the other, right?
Okay, so let's now define a virtual property
that contains the tour duration in weeks.
And so that's a field basically
that we can very easily convert from the duration
that we already have in days, right?
And so here is how it works.
We define that virtual properties on the tour schema,
and so we say, tourSchema.virtual and then the name
of the virtual property.
So let's call it duration weeks,
and then on there we need to define the get method.
And that's just because this virtual property here
will basically be created each time
that we get some data out of the database.
And so this get function here is called a getter.
Now in here we pass a function,
and actually this call back function
is gonna be a real function, so not an arrow function,
and I'm gonna explain to you why in a second.
Now how do we then basically define
the virtual property?
Well it's very simple, all we have to say
is that we want to return this, .duration in this case,
divided by seven.
So this is how we calculate the duration in weeks,
so the duration in days divided by seven
because there are seven days in the week,
and so that's then the duration in weeks.
For example, if a tour has seven days,
then it's of course gonna be one week.
Now I used this regular function here
because remember, an arrow function does not get
its own disk keyword.
In here we actually need the disk keyword
because the disk keyword in this case
is going to be pointing to the current document.
And so usually when we want to use this,
then we should always use a regular function.
So really everywhere in Mongoose,
I'm gonna always be using these regular functions
that we're used to.
So give it a save here, and that's actually it.
That's how we define duration weeks,
which is not going to be persisted in the database,
but it's only gonna be there as soon as we get the data.
Now right now it's actually not gonna be there yet,
because there's one piece missing here,
so let me start by showing you that.
So if we try to get all tours,
you will see that duration weeks is nowhere
to be found here.
And that's because we need to explicitly define
in our schema that we want the virtual properties
in our output.
And so remember how I said that into this Mongoose.schema,
we can pass in not only the object
with the schema definition itself,
but also an object for the schema options.
And so let's add that here at the end,
so this first object here is the schema definition,
and now second an object for the options.
And what we need to specify here is the two JSON
property here, and what we say is then
that each time that the data is actually outputted as JSON,
we want virtuals to be true.
So basically the virtuals to be part of the output.
And now I'm duplicating this because we also
want to say to object.
So basically when the data gets outputted
as an object.
And so if we now go back here, we should then
be able to see duration weeks.
Let's wait for it, and indeed, here it is.
So it's five days, and so that is 0.71 weeks.
Here we have seven days, and so that's one week.
Okay, so that actually works, great.
Now one thing that we need to keep in mind
is that we cannot use this virtual property here
in a query, because they're technically
not part of the database.
So we can not say, for example,
tour.find where duration weeks is equal to one.
That's not gonna work, again because this property
is not actually part of the database.
Now of course we could also have done this conversion
each time after we query the data, for example,
like in a controller, but that would not
be the best practice simply because we want to try
to keep business logic and application logic
as much separated as possible, remember?
So that was that whole talk about fat models
and thin controllers that we talked about before
which says that we should have models
with as much business logic as we can offload to them
and thin controllers with as little
business logic as possible.
And so virtual properties like this are actually
a good example of how we can achieve
that kind of architecture.
So knowing the duration in weeks
is a business logic because it has to do
with the business itself, not with stuff like requests
or responses, and so we do the calculation
right in the model where it belongs
and not in the controller.