‫Welcome back to the next video.
‫And let's keep it going now with a new
‫and pretty advanced Mongoose feature
‫called 'Virtual Populate.'
‫So, at the point, we have populated
‫the reviews with the tour and
‫the user data right here, right?
‫And so, right now, when we query for reviews,
‫we get access to that information.
‫However, that still leaves one problem unsolved.
‫So, how are we going to access reviews on the tours?
‫So basically, the other way around.
‫So, let's say that I queried for a specific tour.
‫And then, how will I get access
‫to all the reviews for that tour?
‫And this problem arises here because
‫we did parent referencing on the reviews.
‫So basically, having the reviews pointing to the tours
‫and not the tours pointing to the reviews.
‫And so, as we said in the beginning of the section,
‫in this case, the parent does not
‫really know about its children.
‫And so, in this example,
‫the tour does not know about its reviews.
‫And sometimes, that's okay.
‫But in this case, we actually want the tour
‫to basically know about all the reviews that it's got.
‫Now, in order to solve this,
‫with what we know at this point,
‫we could have two solutions.
‫And the first one would be to manually query
‫for reviews each time that we query for tours.
‫But it would be a bit cumbersome
‫doing it manually like this.
‫And the second solution could be to also
‫do child referencing on the tours.
‫So basically, keep an array of all
‫the review ID's on each tour document.
‫Then, all we would have to do
‫is to populate that array, right?
‫But, we actually already ruled out doing this
‫right in the beginning because
‫we do not want to store that array
‫of review ID's that could then grow
‫indefinitely in our database, right?
‫And that's actually exactly why we picked
‫parent referencing in the first place.
‫However, there is great solution for this.
‫And that's because Mongoose actually offers us
‫a very nice solution for this problem
‫with a pretty advanced feature called 'Virtual Populate.'
‫So with 'Virtual Populate,' we can actually
‫populate the tour with reviews.
‫So, in other words, we can get access
‫to all the reviews for a certain tour,
‫but without keeping this array of ID's on the tour.
‫So, think of 'Virtual Populate' like a way
‫of keeping that array of review ID's on a tour,
‫but without actually persisting it to the database.
‫And so that then solves the problem that we have
‫with child referencing, right?
‫So, it's a bit like virtual fields, but with populate, okay?
‫So, just to illustrate that,
‫let's go to our tour model here.
‫And so, what I just described would be,
‫in theory, to do something like this.
‫So, on our tour model,
‫we would add a field called 'Reviews.'
‫(keys clicking)
‫And then set the type to Mongoose.Schema.ObjectId.
‫(keys clicking)
‫And you don't need to write this.
‫I'm just doing it to show it to you.
‫(keys clicking)
‫And then connect it with 'Review.'
‫And of course, this here would have to be an object.
‫But, what matters here is that this is basically
‫how we would implement child referencing.
‫So the tour referencing reviews, okay?
‫But again, we do not want to do it.
‫So instead, we're going to implement 'Virtual Populate.'
‫(keys clicking)
‫All right. And it works like this.
‫So we do it here on the tour schema.
‫(keys clicking)
‫And we still do it .virtual.
‫So just like with this virtual field here, duration week,
‫then we type in the name of the virtual field.
‫So let's call it 'Reviews,'
‫and then an object of some options.
‫And the first one is the name of the model
‫that we want to reference.
‫And so that works just like with the normal referencing.
‫(keys clicking)
‫So again, the name of the model.
‫So, 'Review' or course, in this case.
‫And now, we actually need to specify the name of the fields
‫in order to connect the two data sets.
‫And this is, for me, the most complicated part
‫of implementing this 'Virtual Populate.'
‫And so, let's make sure you really understand this part.
‫So here, we need to specify two fields.
‫The foreign field and the local field.
‫So let us start with the foreign field.
‫And so, this is the name of the field in the other model.
‫So in the Review model in this case,
‫where the reference to the current model is stored.
‫And that is, in this case, the Tour field, right?
‫So, let's take look at that.
‫And so, again, in our review model,
‫we have a field called 'Tour.'
‫And so this is where the ID of the tour is being stored.
‫And so that's why here, in this foreign field,
‫we specify that name of that field
‫in order to connect these two models, okay?
‫And now we need to do the same for the current model.
‫So, we need to say where that ID is actually stored
‫here in this current Tour model.
‫So, local field.
‫And that is, the ID.
‫So, _ID, okay?
‫And so, again, this _ID, which is how
‫it's called in the local model,
‫is called 'Tour' in the foreign model.
‫So, in the Review model. Okay?
‫And so again, this is how we connect
‫these two models together.
‫Let's us write here that this is
‫'Virtual Populate,' okay?
‫And so now, with this setup, we can actually use
‫Populate just like we did before.
‫And so what we want to do now is to go ahead
‫and populate the tour when we only
‫get one single tour, okay?
‫So here in Postman, it is in this situation of 'Get Tour.'
‫Okay? Let's see of this actually exists.
‫And it does, but it's this weird test tour.
‫And so, let's actually do it with this 'Forest Hiker' one.
‫All right.
‫So, when we get this tour,
‫we now want to populate the reviews.
‫And it should already be here as an empty array.
‫Ah, here it is.
‫It's not an empty array, but it's set to 'null.'
‫But the virtual field is actually
‫already there with the reviews.
‫But it's null at this point because
‫we didn't yet populate it, okay?
‫And again, we only want to populate it
‫here in the 'Get One Tour,' and not
‫in the 'Get All Tours' because that
‫would be a bit too much information to send
‫down to a client when they get all the tours.
‫Also, when we're getting all the tours,
‫that's usually to build an overview page.
‫And in that case, we usually
‫do not need access to all the reviews.
‫We only need that when we are
‫really displaying just one tour.
‫Okay? And so, I think it makes sense
‫to only do this populate on 'Get One Tour.'
‫So, let's do that populate actually
‫right in the controller.
‫So, the tour controller and down here
‫where we have 'Get Tour.'
‫And so, that's actually very easy.
‫Only to do is to call 'Populate' after the other query,
‫and then simply pass the name
‫of the field that we want to populate.
‫And so, as we already know, that is called 'Reviews.'
‫And, so that should actually be it already.
‫All right?
‫So, let's test this now, and take a look at this.
‫And indeed, we now get our complete review right here.
‫All right? So that got populated.
‫And so it means that our Virtual Populate
‫is actually working.
‫Now, you might start to see that
‫this is creating kind of a problem
‫because this here is basically creating
‫a chain of populates.
‫And that's not ideal at all.
‫So, we have the tour being populated with reviews.
‫But then the reviews also get populated
‫with the tour again, and also with the user.
‫And then also the tour is also
‫getting populated with guides.
‫Which in this case, is not happening
‫because there are no guides.
‫But if there were, then we would have yet another populate.
‫And so here we would have a chain of three populates.
‫And so for performance, that's of course, not ideal at all.
‫Especially here with the tour.
‫So we have the tour populated with reviews.
‫And in the reviews, we again have the data about the tour.
‫And so that doesn't make much sense at all.
‫So, it's kind of a mess now.
‫SO, the solution that I'm going to use here
‫is to actually turn off populating
‫the reviews with the tours, okay?
‫So basically, we do not need this data here on each review.
‫So in this case, I think that's a good solution.
‫But of course, again in your case,
‫it will always depend on how
‫your application works in your specific case.
‫But in this app, it's more logical to
‫really have the reviews available on tours,
‫and it's not that important having the tour
‫available on the review, okay?
‫So, let's turn that populate off basically,
‫in the Review model.
‫Okay?
‫So, let's just comment this part out,
‫copy it down here,
‫and so, basically get rid of this first one.
‫Now all right?
‫Get ready to save.
‫Let's try it again.
‫And so, now we should only see the ID of the tour here.
‫Okay? And indeed, that's exactly what we get.
‫Okay? Now with this, of course,
‫we still do parent referencing, okay?
‫We still keep a reference to the tours here,
‫but we simply do not populate it.
‫And again, because we don't always
‫need that data right here.
‫All right. Let's just quickly recap what we did here.
‫So, we started doing only parent referencing on the review.
‫But that made it so that on the tours,
‫we had no access to its corresponding reviews.
‫And the easiest fix for that would be
‫to also do child referencing on the tours.
‫But the problem with that would be
‫that we do not actually want to keep
‫an array of all the child documents
‫on the parent document, right?
‫Because again, we don't want to allow
‫arrays to grow indefinitely.
‫So instead of doing that,
‫we implemented virtual populates like this.
‫All right? So, just like this.
‫And this allows us to basically do the exact same thing.
‫So, keeping a reference to all the child documents
‫on the parent document,
‫but without actually persisting that information
‫to the database.
‫And so then, after having this virtual populate set up,
‫all we needed to do is to basically use
‫Populate just like we did before with the real references.
‫And then, finally, we also turned off
‫one of the populates that we had on the review.
‫So, this one here, where we populated
‫the tour ID, because that was creating
‫an inefficient chain of populates.
‫And so that's, of course, something that we do not want.
‫And so, in the end, we ended up with
‫a result like this, okay?
‫Great.
‫So, I hope that made sense to you.
‫And so with this, we actually wrap up for now
‫of this part of populating, okay?
‫And so now let's move on to a next topic,
‫which is basically creating nested routes.