1
00:00:00,000 --> 00:00:04,652
[MUSIC]

2
00:00:04,652 --> 00:00:11,190
I guess by now, your head is infested
with mongooses or is it mongeese?

3
00:00:11,190 --> 00:00:16,500
Well, I'm no English major, so
I have no clue what the plural is.

4
00:00:16,500 --> 00:00:22,770
In any case, that brings us to the topic
of this lecture, Mongoose population.

5
00:00:22,770 --> 00:00:25,120
What exactly is Mongoose population and

6
00:00:25,120 --> 00:00:29,800
how is it useful in our
express application?

7
00:00:29,800 --> 00:00:31,190
Let's talk about that next.

8
00:00:33,100 --> 00:00:38,275
As we realized, document databases,
the NoSQL databases,

9
00:00:38,275 --> 00:00:41,767
are not designed with relations in mind.

10
00:00:41,767 --> 00:00:46,570
Everything that you need in a document is
stored completely within the document.

11
00:00:46,570 --> 00:00:53,650
Well, that is pretty much the way things
operate with NoSQL databases like MongoDB.

12
00:00:53,650 --> 00:00:58,490
So you do not have support for
relations that you might be

13
00:00:58,490 --> 00:01:03,065
more familiar with from
the relational database world.

14
00:01:03,065 --> 00:01:08,060
Where you have records and then records
can reference other records and so on.

15
00:01:08,060 --> 00:01:12,510
And then you do joins in order to join the
information from the records and so on.

16
00:01:12,510 --> 00:01:17,030
So that kind of support doesn't
exist in NoSQL databases,

17
00:01:17,030 --> 00:01:19,010
at least to a large extent.

18
00:01:19,010 --> 00:01:25,120
MongoDB has taken a few steps in that
direction, even with the NoSQL databases.

19
00:01:25,120 --> 00:01:31,030
But in general, document databases expect
that all documents are self-contained.

20
00:01:31,030 --> 00:01:36,740
So which means all the information that
is required is within the same document.

21
00:01:36,740 --> 00:01:41,270
Now of course, there are situations
where you have other documents that

22
00:01:41,270 --> 00:01:43,657
already contained the information.

23
00:01:43,657 --> 00:01:47,561
And you may want to pull that
information into your existing document,

24
00:01:47,561 --> 00:01:50,580
rather than duplicating that information.

25
00:01:50,580 --> 00:01:57,390
So this is where MongoDB or Mongoose,

26
00:01:57,390 --> 00:02:04,290
allows you to store references to other
documents within a current document.

27
00:02:04,290 --> 00:02:08,953
The reference to the other document
is done by using the ObjectID of that

28
00:02:08,953 --> 00:02:10,125
other document.

29
00:02:10,125 --> 00:02:14,773
Now if that is the case, then Mongoose
allows you to perform a way of

30
00:02:14,773 --> 00:02:19,588
taking the information from the other
document and then enclosing it

31
00:02:19,588 --> 00:02:25,010
inside the correct document using
the Mongoose population support.

32
00:02:25,010 --> 00:02:28,230
That is what we will discuss
in a little more detail.

33
00:02:28,230 --> 00:02:33,227
Mongoose itself, as we realize,
being a module built

34
00:02:33,227 --> 00:02:38,336
on top of MongoDB,
doesn't have explicit supports for

35
00:02:38,336 --> 00:02:43,135
joins, the way we talk about
joins in the SQL world.

36
00:02:43,135 --> 00:02:48,471
To understand how this referencing of the
other document in a document helps us and

37
00:02:48,471 --> 00:02:53,210
how it is actually structured,
let's take a look at an example.

38
00:02:53,210 --> 00:02:58,420
In this example,
we'll look at the dishes document that we

39
00:02:58,420 --> 00:03:01,210
have been using in our exercise.

40
00:03:01,210 --> 00:03:04,540
In the dishes documents that
we store on the server side,

41
00:03:04,540 --> 00:03:07,590
we noticed that we also
store the comments.

42
00:03:07,590 --> 00:03:12,366
And within the comments, we also store
an author field within the comments.

43
00:03:12,366 --> 00:03:16,750
And author field explicitly
contains the name of the person who

44
00:03:16,750 --> 00:03:19,890
submitted that specific comment.

45
00:03:19,890 --> 00:03:24,961
Now, since we already
have a users document

46
00:03:24,961 --> 00:03:30,453
within our database,
as we saw in this module.

47
00:03:30,453 --> 00:03:35,151
We had extended our expert server
to support users and thereby,

48
00:03:35,151 --> 00:03:40,440
you can register a user and
that you can authenticate users and so on.

49
00:03:40,440 --> 00:03:45,790
So the user document can carry additional
information about the user already.

50
00:03:46,810 --> 00:03:49,302
And so
when a comment is posted by the user,

51
00:03:49,302 --> 00:03:53,043
instead of storing the user's
name within the comment itself,

52
00:03:53,043 --> 00:03:57,360
why not have a reference to the specific
user that has posted the comment?

53
00:03:58,360 --> 00:04:02,570
This is helpful not only
in terms of being able to

54
00:04:02,570 --> 00:04:07,680
deal with the fact that this comment
is posted by the specific user.

55
00:04:07,680 --> 00:04:13,934
Later on, we will see that if you
need to allow users to modify or

56
00:04:13,934 --> 00:04:19,126
delete documents,
you may wish to restrict the kind

57
00:04:19,126 --> 00:04:24,436
of operation of a specific
user to only those comments

58
00:04:24,436 --> 00:04:28,937
that that specific user
has posted earlier.

59
00:04:28,937 --> 00:04:36,649
Even though we are using sub-documents
within our Mongo document.

60
00:04:36,649 --> 00:04:42,292
If we can reference another document
in the sub-document using ObjectIds,

61
00:04:42,292 --> 00:04:45,415
then Mongo helps us to
do population of this

62
00:04:45,415 --> 00:04:50,450
information from the other document
into the current document.

63
00:04:50,450 --> 00:04:54,370
So this is where Mongoose
population comes to our rescue.

64
00:04:54,370 --> 00:04:57,770
Taking this idea further,
let me show you a detailed

65
00:04:57,770 --> 00:05:02,600
example from the comment schema
that we have defined earlier.

66
00:05:02,600 --> 00:05:06,850
So in the commentSchema,
we already have the rating field and

67
00:05:06,850 --> 00:05:10,080
the comment field which we
have already specified there.

68
00:05:10,080 --> 00:05:13,320
We also used to have
the author field earlier.

69
00:05:13,320 --> 00:05:18,133
For the author field earlier,
we were storing the author as

70
00:05:18,133 --> 00:05:23,270
a string and,
The default value also for the author.

71
00:05:23,270 --> 00:05:28,285
Now in storing the author as
a type string, if we now turn

72
00:05:28,285 --> 00:05:34,200
the author into a type of
mongoose.Schema.Types.ObjectId.

73
00:05:34,200 --> 00:05:39,350
So which means that the author
field now will contain an ObjectID,

74
00:05:39,350 --> 00:05:42,870
which is a reference to a user document.

75
00:05:42,870 --> 00:05:46,090
How do you ensure that this is
referencing a user document?

76
00:05:46,090 --> 00:05:51,500
So this is where this additional property
called ref, which specifies that

77
00:05:51,500 --> 00:05:56,160
the schema of the document that you are
referring here is of the type, the User,

78
00:05:56,160 --> 00:05:59,590
schema and the model that we
have already added earlier.

79
00:05:59,590 --> 00:06:05,144
So in this case, the comment schema is now
extended to store the author information,

80
00:06:05,144 --> 00:06:08,706
but the author information
is in a form of an ObjectId.

81
00:06:08,706 --> 00:06:15,480
Which is a reference to the user document
that is already stored in our database.

82
00:06:15,480 --> 00:06:17,750
Now, how does this help us?

83
00:06:17,750 --> 00:06:22,667
This is where, as a I said,
Mongoose population comes to our help.

84
00:06:22,667 --> 00:06:25,120
So how does Mongoose population work?

85
00:06:25,120 --> 00:06:30,150
With Mongoose population,
the way Mongoose population works is that

86
00:06:30,150 --> 00:06:35,363
it automatically replaces specified
paths within a current document.

87
00:06:35,363 --> 00:06:40,850
Which has reference to another document by
the information from that other document.

88
00:06:40,850 --> 00:06:46,282
So in the comment schema, for example,
you have an author field that

89
00:06:46,282 --> 00:06:53,070
is referring to the ObjectId of the user
document that is already in your database.

90
00:06:53,070 --> 00:06:58,963
So with Mongoose population, when you ask
Mongoose to populate this dish document,

91
00:06:58,963 --> 00:07:03,820
then it'll populate the information
about the author in the comment field

92
00:07:03,820 --> 00:07:05,240
from the user document.

93
00:07:05,240 --> 00:07:09,447
So the information about the specific
author that is referenced there will be

94
00:07:09,447 --> 00:07:12,130
fetched and added into your dish document.

95
00:07:12,130 --> 00:07:16,820
And the compound document will be
constructed and then sent back to you.

96
00:07:16,820 --> 00:07:19,370
How do we ensure that this happens?

97
00:07:19,370 --> 00:07:25,020
This is where that cross-referencing with
the ObjectId, as we have seen, helps us.

98
00:07:25,020 --> 00:07:30,890
How does the population
actually happen in code?

99
00:07:30,890 --> 00:07:33,350
Taking a look at how we would populate,
for

100
00:07:33,350 --> 00:07:38,090
example, the dishes document
we have just seen earlier.

101
00:07:38,090 --> 00:07:43,650
Earlier we were doing Dishes.find to
find all the dishes in our database.

102
00:07:43,650 --> 00:07:48,645
Now, once you find the Dishes document,
then you can say populate.

103
00:07:48,645 --> 00:07:52,647
And then supply within the populate,
as a parameter,

104
00:07:52,647 --> 00:07:56,130
the specific field that
needs to be populated.

105
00:07:56,130 --> 00:07:59,380
So here we are specifying comments.author.

106
00:07:59,380 --> 00:08:02,270
Now the expectation is that
the comments.author field is

107
00:08:02,270 --> 00:08:06,550
actually an OjectId which
references to the user document.

108
00:08:06,550 --> 00:08:10,502
And that is how we have set up
our comment schema already.

109
00:08:10,502 --> 00:08:16,418
So this populate call that we
perform here will then go and

110
00:08:16,418 --> 00:08:24,937
fetch from the database each individual
author's record or the user's record.

111
00:08:24,937 --> 00:08:27,457
And then take that user document and

112
00:08:27,457 --> 00:08:33,505
populates it into the dishes document to
construct the compound document from here.

113
00:08:33,505 --> 00:08:35,525
And then after that, of course,

114
00:08:35,525 --> 00:08:39,579
there some is subsequent handling
of data that you have obtained.

115
00:08:39,579 --> 00:08:44,640
And then replying or returning the data to
the client can take place at this point.

116
00:08:44,640 --> 00:08:49,110
But of course, let me caution you
that this population operation is

117
00:08:49,110 --> 00:08:52,020
not an easy task for the server to do.

118
00:08:52,020 --> 00:08:56,825
Because every single dish, you will
have to examine each and every comment.

119
00:08:56,825 --> 00:09:01,385
Then for each and every comment, then
you need to find out their ObjectId for

120
00:09:01,385 --> 00:09:02,034
the user.

121
00:09:02,034 --> 00:09:04,580
Then you go and
fetch that user document and

122
00:09:04,580 --> 00:09:07,203
then populate it inside the dish document.

123
00:09:07,203 --> 00:09:09,329
And then, that has to be repeated for

124
00:09:09,329 --> 00:09:13,113
every single comment that is
contained in that Dishes document.

125
00:09:13,113 --> 00:09:18,437
It essentially means that it'll take
a much longer time for the server side

126
00:09:18,437 --> 00:09:23,720
to complete the request and send back
the information to the client side.

127
00:09:23,720 --> 00:09:31,020
So I would suggest that you should
use populate very judiciously.

128
00:09:31,020 --> 00:09:35,410
You should use it only in circumstances
where you really need that information.

129
00:09:36,590 --> 00:09:42,529
If, for example, you're simply
constructing the menu for your restaurant.

130
00:09:42,529 --> 00:09:46,522
When you're just constructing the menu for
your restaurant,

131
00:09:46,522 --> 00:09:51,267
you may not really need to populate
the information about the author of each

132
00:09:51,267 --> 00:09:54,010
comment into the comment document at all.

133
00:09:54,010 --> 00:09:57,270
Because when you are just rendering
the menu for your restaurant,

134
00:09:57,270 --> 00:10:01,730
you are not going to be showing
the comments for that specific dish.

135
00:10:01,730 --> 00:10:06,457
But instead, if the user is
examining a specific dish and

136
00:10:06,457 --> 00:10:09,804
wants to see the comments at that point,

137
00:10:09,804 --> 00:10:13,660
you may wish to execute
a server side request.

138
00:10:13,660 --> 00:10:19,383
And then fetch the comment information
with the other author information

139
00:10:19,383 --> 00:10:24,540
populated in and obtain that for
use within our client side.

140
00:10:24,540 --> 00:10:30,240
So again, populate is a wonderful
way of doing things when required,

141
00:10:30,240 --> 00:10:35,610
but use it very judicially, only when
you really require the information.

142
00:10:35,610 --> 00:10:38,370
So that flexibility that
populate provides for

143
00:10:38,370 --> 00:10:42,540
us is the fact that we don't need
to populate when we don't have to.

144
00:10:42,540 --> 00:10:46,990
But we can populate the information
when we really need that information.

145
00:10:48,030 --> 00:10:51,450
With this quick understanding
of Mongoose population,

146
00:10:51,450 --> 00:10:57,280
let's move on to the exercise where
we will modify the Dishes schema,

147
00:10:57,280 --> 00:10:59,840
the comments schema
within the Dishes schema.

148
00:10:59,840 --> 00:11:04,730
And then use Mongoose populate to populate
the information within our dishes

149
00:11:04,730 --> 00:11:09,255
when we are returning the dish
information to the server side.

150
00:11:09,255 --> 00:11:15,745
Also, this also implies that when a
comment is being added to a specific dish,

151
00:11:16,775 --> 00:11:22,210
the author of the comment's information
has to be captured on the server side.

152
00:11:22,210 --> 00:11:26,079
Now, it so happens that the way
we have developed our servers,

153
00:11:26,079 --> 00:11:29,740
we already have this information
being provided for us.

154
00:11:29,740 --> 00:11:34,870
When we authenticate the user, the user's
information is already loaded into every

155
00:11:34,870 --> 00:11:37,580
request that comes in
from the client side.

156
00:11:37,580 --> 00:11:41,200
And so they use that user
information's available to us.

157
00:11:41,200 --> 00:11:46,170
So when we are posting the comment
on the server side, we will also

158
00:11:46,170 --> 00:11:52,370
capture the user's ID and then store it in
the author field of the comment schema.

159
00:11:52,370 --> 00:11:55,430
This should be done automatically
on the server side.

160
00:11:55,430 --> 00:12:00,740
The client should not be allowed to
fill in the author field explicitly.

161
00:12:00,740 --> 00:12:04,348
But the server side should
validate the user and only for

162
00:12:04,348 --> 00:12:10,020
users that are signed in, you would allow
them to, first of all, post comments.

163
00:12:10,020 --> 00:12:12,688
And then when they post comments,

164
00:12:12,688 --> 00:12:18,392
you will automatically fill in the author
field for that comment document

165
00:12:18,392 --> 00:12:23,740
by substituting the author field
with the ObjectId of the user.

166
00:12:23,740 --> 00:12:25,920
Now, in the exercise,
you will see me doing that.

167
00:12:25,920 --> 00:12:30,780
So watch out for
that specific thing in the exercise.

168
00:12:30,780 --> 00:12:33,245
With this, we complete this lecture,

169
00:12:33,245 --> 00:12:38,109
let's proceed on to the exercise to
examine the use of Mongoose population.

170
00:12:38,109 --> 00:12:44,079
[MUSIC]