0:00
[MUSIC]
Now that we have learned about Mongoose Population and
how it enables us to populate one document with information from another document.
In this exercise,
we will modify the extra stress server that we have been working on so far.
In that dish schema that we have defined earlier we had comments,
and from the comments we had the other field that
we used to store the details about the author.
In this exercise, we will turn the outer
field into a reference to a user document.
And we will use Mongoose Population to populate the information into the dishes
document has been required in order to supply the information to the client.
Now the use of populate and Mongoose Population should be done judiciously,
so as not to cause too much of overhead on the server side.
Now in this exercise, we're going to use it simply to populate the information
into that outer field of our comments.
So let's proceeded exercise to learn how we use Mongoose Population.
1:45
String.
And the default would be an empty string.
So the firstname, as the name implies,
stores the first name for the user.
And then we'll have another field called lastname, which is also of the same kind.
So I'm just going to copy these two piece of information, and then copy it in here.
And so, now our user document will contain in addition
to the username and password, username and the hash and
salt that we have seen earlier that is automatically
added by the Passport-Local-Mongoose module.
We'll also have the firstname and the lastname for the user being defined here.
Later on, we will see how we would initialize these values
by modifying the users registration process.
2:51
Now once we have completed this, so this way the user's
information can simply be retrieved by looking up the user document here.
So now that we have the information about the user in the user document,
going into the dish schema, so going into the dishes.js file.
In the dish schema earlier,
we were storing the author of the document in the form of a string here.
Now we're going to be taking advantage of the fact that we have
the support of Mongoose Population.
So I'm going to turn that comment field from a string into
mongoose.Schema.Types.ObjectId.
So this way this, sorry, wrong field.
I meant to turn the author field
into mongoose.Schema.Types.ObjectId.
So the author field now storing the string will
have a reference to the user document.
So when I turn the author field into this type,
then the second property that I define here will be a reference,
which would be a reference to the User model there.
So this way, we are now going to be connecting this author field.
And this author field will simply store a reference
to the ID of the user document and
storing the details about the author in the form of na.
Now when we do that, we can use mongoose populate
to populate this information into our dishes document whenever required.
5:24
So right at that point we will say, Dishes.find,
and we will say after this populate so
we are using the population support in Mongoose.
And we will say, populate, comments.author.
So by stating this, we are saying when the dishes are being constructed.
Dishes document has been constructed to send back that apply to the user.
They're going to populate the author field inside there
from the user document in there.
So this call to the populate will ensure that the author field
will be populated with the information as required.
Similarly, going to the dishId here, even in the dishId, same thing.
We will say populate and
comments.author.
Added into the dishes find
by ID in the get of the slash dishId endpoint.
Similarly, in the comments
also when we retrieve the dish,
we'll say populate comments.author here.
And the same thing also in the dishRouter
dishId comments, comment Id also.
So we're going to be populating this information there.
Now of course what this means is that,
when you are posting the dish earlier you were including
the author information in the body of the message.
So now here, when we try to push the comment into that,
so this post corresponds to the dishId comments field.
So this is how we were posting a comment to a specific dish.
So now in this post,
since we are not storing the information about the author anymore.
So what we need to do is when we push the.
Item into the other field there.
So here when you're populating the information into the dish, we will
have to first recall that the body contains the comment already.
But the author property will not be there in the body of the message anymore.
But depending on which user is posting this information,
we can immediately populate the author field.
Now, how do we know which user is posting this information?
The fact that we have done the verifyUser here for
the post, means that a specific user is posting this information.
And by doing the verifyUser,
we would have already loaded in the req.user into the request object.
And in the request objects, so we can go in and say req.user._ID here.
So again, let me reiterate this point.
How are we obtaining the author's information here?
Now recall that we updated there dish schema so
that the author field and the comment will simply store
9:15
the object ID referring to the user that is posting this comment.
Now how do we know which user is posting this comment?
Now again, to reiterate this point, recall that when we verified the user
here by calling authenticate.verifyUser.
The passport authorize JWT would have loaded the user
information into the request body in the form of req.user.
So that user will contain the ID
of the specific user that is actually posting this comment.
So we have already verified the authenticity of the user, and so
the user ID can simply be obtained by saying req.user._id.
And that user's ID, I will assign this to the other field of the comment.
Now, when the comment comes in, the comment in the body of the request message
will only contain the rating field and the comment field.
We don't want to explicitly send the author field anymore from the client side.
Instead, that should be automatically inserted on the server side,
based upon the authenticity of the user.
That's the point that I've been reiterating in this
modification that I have done here.
So if that user's information is automatically obtained from the req.user,
that is loaded into the body of that request message
by the authenticate verifyUser.
Which is going to use passport.authenticate with the JWT
strategy there.
So with this modification to the dish router,
now the last point that we need to consider
is the fact that in the user.js file, we have now added in two fields.
The first name and the last name field, which by default will be empty strings.
So when the user is registering, we should allow the user to
supply the first name and the last name in that registration process.
Now where does that take place?
That takes place in the users.js file.
So go into users.js file when the user posts on that /signup.
Earlier we were only posting the username and password.
In addition to those two in that JSON
object that we included the body of the request message coming in.
That post request message coming in from the client side,
we can also include the first name and the last name for the user.
So when the first name and the last name for the user is included.
So what am I going to do here?
So recall that when you say user.register,
at this point the user information comes in.
And then you have submitted the username here and you have also assigned a password
here which will be turned into the hash and solved by the password local mongoose.
Now if there is no error, that means that the user's registration was successful.
And so at this point, what we will do is we
will say if (req.body.firstname).
So which means that the body of the incoming request message,
if it contains the first name, then we'll say
user.firstname = req.body.firstname.
Similarly for the last name also.
So at this point, we would have the user available here.
See the user is coming in as the second parameter to this callback function here.
So we are setting up the first name by changing the first name
property inside the user document here saying req.body.firstname, if it exists.
Then we'll set the users first name to that,
similarly if the req.body.lastname is available.
So we'll also update the user's last name as req.body.lastname.
And once we have done these two changes to the first name and the last name.
Then we need to save
the modification that we have done to the user, so we have just updated the user.
So we'll say user.save, and then this will
return, The error or the user.
So if the modification has been saved properly, then it will return the error.
Otherwise it will return the user value.
And this passport.authenticate, we will do it inside this user here.
15:02
If there is no error,
then of course you authenticate the user by calling passport.authenticate
with the local to ensure that the user registration has been successful.
And this should be correctly done and
when each case you will return this message back to the client site.
And we need to close this user.save here.
So make sure that you close this endpoint correctly.
So user.save is closed here and that's it.
These are the changes that we need to make to the user.
So whereby after the user is registered with the given user name and
the given password.
Then after the user is successfully registered,
then we will set the first name and the last name field.
Of the user document by using these two here.
16:38
And delete the user what we have registered earlier.
So we'll say use conFusion.
And then we'll say db.users.find() so
we know that this particular user has been registered earlier.
But when we registered that user, we did not register the first name and
the last name for the user.
So I'm going to delete this user and then re-register the user.
So to do that using the Mongo Ripple, I'll say db.users.drop.
And then we'll say, db.users.find and that should return an empty.
No users registered there and then we'll exit the Mongo Ripple.
And so once you have removed that registered user,then
let me start my server.
17:36
And once the server is up and running, let's go to Postman and
register a new user along with the first name and the last name of the user.
Then, we will login as that user and then we'll look at how
the Mongo's population helps us to populate the information about the user
automatically into the document.
Now, going to Postman, let me do a sign up of a new user.
So I'm doing a host localhost column 3,000 users sign up.
And in the body of the message we have the username and
then the password already in there.
Let me add in two additional fields.
"firstname", "lastname",
18:47
So once I register the user, you can see that the registration was successful.
Now let me login as this user.
So to login as the user let me do a post and
cross check to make sure.
So I'm doing a post for users login.
Let me cross check and I see that the username and
password is correctly typed in there.
So when I login, I should be successfully logged in and
I should be able to obtain this token there.
Because this token is essential for
us to be able to add in a dish to our server site.
So after you obtain the token, copy this token string and
save it because you will need that in the authorization header for
the post put and delete operations that you're going to perform later.
So let me copy that token.
Now, normally, the way that I would keep these tokens is that I'll just open a text
document and then copy and paste it into the text document.
So that for some subsequent Postman requests, I can simply copy this string
and then paste it into the into the authorization header if required.
So let me copy that token.
And here I have a text document open here.
So I'm going to paste that string into this text document.
So here, we have the token that we have obtained.
Let's now go and post a dish to our server.
Going back to Postman, let me post a dish to the server.
So this is where I will choose the post here and
inside here I have this information that I used earlier.
But for the comments,
now recall that earlier we had the other field we just toting a string.
So all these comments are not valid so
I'm going to delete all these comments from submission.
Because now we expect the user to post comments on their own.
And when the user to posts comments, we will automatically add in the ID
21:14
of the user into the author field of the comments.
So let me post this dish here and go into the header, in the authorization header,
I'm going to say, Bearer and
then paste the, Token and then submit.
I should do a POST on that.
So we'll say post and so when I post now you'll see
that this dish has been posted on the server side.
So that's why it ends with the comments array been empty at this moment.
So after they post this dish, let me copy the ID of this dish.
So let me copy this ID for
the dish because I would need that to post comments for this dish.
And then go into my text editor, I am going to save that ID of the dish here.
22:18
Now of course once you build your client side your client will automatically have
all this information.
And so your client will automatically be able to send the token and so what.
So you don't need to do this cut and paste thing.
But with Postman this is the only way that we can add in information
to our Postman requests that go out from Postman to the server.
Now, in order to convince ourselves that this dish actually exists,
let me do a git on the local host column 3,000 dishes.
And when I do a git,
you can actually see that this particular dish exists on the server side.
So let's now try to post a comment.
So to post a comment,
let's do a POST, and we'll say,
localhost:3000/dishes/ and
the ID of the dish that I just copied, and /comments.
And when you post on the comments, you need to make
sure that in the body, they will add in there comment here.
So a typical comment contains a rating,
24:26
Let's now post this comment and then the comment is posted.
Let's look at the return value here.
So as you browse down you can see that
the dish through which the comment has been added has been returned.
Notice that the disinformation is there, but not in particular.
What is contained in the comment that has been posted here?
So as you can see, you already know that the updated and
the createdAt fields are automatically added in by Mongoose.
The rating and the comment that we submitted are right there, but
note how the author field now contains the ID corresponding to the user.
Now, as we saw in the code how the author field information is added in.
Now if you do a get on the dishes, you will notice that
this author field will be automatically filled in by the user's information here.
So let's now do a get on the localhost:3000/dishes.
So when we now do a get on this pont, you now notice that
in the dishes here, right there, the information
about the dish is already present but not how the comment is now constructed.
The comment now contains, The rating comment fields as we saw earlier,
that updated it and creted it, but note what happened to the author field here.
So when you do a get request, because we did a populate on the server side.
When the get operation is invoked.
The populate has automatically populated that author
information into position in the author field here.
So in there you can see that from the author you can now look up the last name
and the first name information automatically from the author field.
So if you need to construct a comment, you now have the rating,
the comment, and also the first name and
the last name of the author automatically included into this document.
And also the username is included into this document.
So this is how you can add in information from another document and
populate a second document with that information before you
reply back from the server side.
So this is the use of Mongoose population and
how we can automatically populate information into a Mongoose document.
27:04
With this we complete this exercise.
In this exercise we have seen the use of Mongoose population.
And you've seen how we can populate information from
one document into another document.
Whereby when we modify the server to do the population, for the request,
Mongoose will automatically take care of populating this information for us.
And all that we need to do is to store the reference
to the other document in the form of the object ID
in the document into which you want to populate this information.
With this, we complete this exercise.
This is a good time for you do a get
with the message Mongoose population.
[MUSIC]