Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated:
1
00:00:00,980 --> 00:00:03,100
In this video, I want to, very quickly,
2
00:00:03,100 --> 00:00:06,510
refactor the API features that we've implemented
3
00:00:06,510 --> 00:00:08,620
over the last couple of lectures.
4
00:00:08,620 --> 00:00:11,760
Now, this is not only to make our code a bit cleaner,
5
00:00:11,760 --> 00:00:15,000
it's also to make it more modular and more reusable
6
00:00:15,000 --> 00:00:15,913
in the future.
7
00:00:17,290 --> 00:00:20,430
So, right now, we have all this code for the features
8
00:00:20,430 --> 00:00:25,050
that we built before in this getALLTours function, right?
9
00:00:25,050 --> 00:00:26,860
And this looks a bit messy.
10
00:00:26,860 --> 00:00:30,160
It's a bit hard to understand, okay?
11
00:00:30,160 --> 00:00:33,900
And, also imagine that we wanted to use these same features
12
00:00:33,900 --> 00:00:35,010
for another resource.
13
00:00:35,010 --> 00:00:38,250
For example, for the users or, later, for the reviews.
14
00:00:38,250 --> 00:00:40,910
It would be not very practical to, basically,
15
00:00:40,910 --> 00:00:43,300
copy the code from here and use it, then,
16
00:00:43,300 --> 00:00:45,670
in the other resources, right.
17
00:00:45,670 --> 00:00:47,360
And so, what I'm going to do is to, now,
18
00:00:47,360 --> 00:00:50,340
create a class in which I'm going to add one method
19
00:00:50,340 --> 00:00:54,070
for each of these API features or functionalities,
20
00:00:54,070 --> 00:00:55,500
as you might call them as well.
21
00:00:55,500 --> 00:00:56,900
All right?
22
00:00:56,900 --> 00:00:59,906
So, let's go ahead and do that here
23
00:00:59,906 --> 00:01:02,950
and I'm going to do it here, for now, then, later on,
24
00:01:02,950 --> 00:01:05,750
I'm actually going to export it to its own file,
25
00:01:05,750 --> 00:01:08,810
basically, to create a reusable module that we can,
26
00:01:08,810 --> 00:01:11,760
later on, import into other controllers.
27
00:01:11,760 --> 00:01:12,960
All right?
28
00:01:12,960 --> 00:01:16,663
So, class, and I'm calling it APIFeatures.
29
00:01:19,260 --> 00:01:20,093
All right.
30
00:01:21,720 --> 00:01:24,510
Then, we start with our constructor function
31
00:01:24,510 --> 00:01:26,840
and remember that this is the function that gets
32
00:01:26,840 --> 00:01:29,990
automatically called as soon as we create a new object
33
00:01:29,990 --> 00:01:33,070
out of this class, all right.
34
00:01:33,070 --> 00:01:36,830
Now, what do I actually want in these API features?
35
00:01:36,830 --> 00:01:41,090
Actually, I'm going to parse in two variables here, okay?
36
00:01:41,090 --> 00:01:45,962
So the mongoose query and also the queryString
37
00:01:45,962 --> 00:01:47,323
that we get from express.
38
00:01:48,410 --> 00:01:51,420
So, basically, coming from the route, all right.
39
00:01:51,420 --> 00:01:53,490
So that's what we usually have access to
40
00:01:53,490 --> 00:01:56,760
in the req.query, okay.
41
00:01:56,760 --> 00:01:59,780
Now, again, I'm passing the query here because I do not
42
00:01:59,780 --> 00:02:03,110
want to query inside of this class because that would then
43
00:02:03,110 --> 00:02:06,040
bounce this class to the tour resource but, again,
44
00:02:06,040 --> 00:02:08,902
I want this to be as reusable as possible.
45
00:02:10,690 --> 00:02:11,523
All right.
46
00:02:11,523 --> 00:02:14,080
So, what we usually do in this constructor function
47
00:02:14,080 --> 00:02:18,490
is to say this.query equals the query that we got
48
00:02:18,490 --> 00:02:21,480
as an argument and then this.queryString
49
00:02:25,130 --> 00:02:27,890
is equal to the queryString.
50
00:02:27,890 --> 00:02:28,723
Okay?
51
00:02:28,723 --> 00:02:32,490
So very simple, very typical constructor function.
52
00:02:32,490 --> 00:02:35,580
And now, as I mentioned, I'm going to create one method
53
00:02:35,580 --> 00:02:39,313
for each of the functionality, starting with filter.
54
00:02:41,860 --> 00:02:42,693
All right.
55
00:02:42,693 --> 00:02:46,490
And so, let's now go ahead and cut the code from here.
56
00:02:46,490 --> 00:02:49,130
Or, actually, I'm going to copy it and them comment it,
57
00:02:49,130 --> 00:02:52,180
so that I don't do any accidental damage.
58
00:02:52,180 --> 00:02:53,710
So, copy and the comment
59
00:02:55,350 --> 00:02:57,120
and put it right here.
60
00:02:57,120 --> 00:02:59,450
So, a couple of things that we need to change.
61
00:02:59,450 --> 00:03:03,350
First on, request.query is not going to be available
62
00:03:03,350 --> 00:03:04,830
inside of this class.
63
00:03:04,830 --> 00:03:07,250
And so, that's why we actually parsed in the queryString.
64
00:03:07,250 --> 00:03:09,930
And so, this here is going to get replaced
65
00:03:09,930 --> 00:03:11,623
with this.queryString.
66
00:03:13,490 --> 00:03:14,323
Okay?
67
00:03:14,323 --> 00:03:16,450
So, again, this is just basic Javascript.
68
00:03:16,450 --> 00:03:20,260
Has actually nothing to do with Note or Express at all.
69
00:03:20,260 --> 00:03:24,760
Then the rest here is okay but this here is not okay at all.
70
00:03:24,760 --> 00:03:29,340
So I do not want to query the tour directly here, remember,
71
00:03:29,340 --> 00:03:32,170
but instead, I simply want to now add this find
72
00:03:32,170 --> 00:03:34,650
to the query that we already have.
73
00:03:34,650 --> 00:03:37,147
So this.query.find
74
00:03:40,560 --> 00:03:43,763
and so, that will then be this.
75
00:03:45,010 --> 00:03:45,860
All right?
76
00:03:45,860 --> 00:03:47,800
Let's, now, get rid of this.
77
00:03:47,800 --> 00:03:50,370
And before we add any more methods here,
78
00:03:50,370 --> 00:03:52,870
let's actually go ahead and use this class
79
00:03:52,870 --> 00:03:54,833
just so this makes more sense to you.
80
00:03:55,700 --> 00:03:56,533
Okay?
81
00:03:56,533 --> 00:03:58,653
So, how is this actually going to work?
82
00:03:59,890 --> 00:04:02,400
And I'm going to do it all here at the end here
83
00:04:02,400 --> 00:04:04,420
under Execute Query.
84
00:04:04,420 --> 00:04:05,350
All right?
85
00:04:05,350 --> 00:04:07,750
And so, what I can do now is to create a variable
86
00:04:07,750 --> 00:04:09,583
called Features, for example.
87
00:04:12,450 --> 00:04:17,300
And then from here, I will create a new API features object.
88
00:04:17,300 --> 00:04:18,160
Okay?
89
00:04:18,160 --> 00:04:21,560
So, basically, creating an instance of this API features
90
00:04:21,560 --> 00:04:23,870
that will then get stored into Features.
91
00:04:23,870 --> 00:04:26,600
And this here, we'll, then, have access to all the methods
92
00:04:26,600 --> 00:04:29,380
that we're going to define in the class definition.
93
00:04:29,380 --> 00:04:30,360
Okay?
94
00:04:30,360 --> 00:04:33,490
So, remember, in here, we need to pass a query
95
00:04:33,490 --> 00:04:34,980
and the queryString.
96
00:04:34,980 --> 00:04:36,983
So, the query, how do we create one?
97
00:04:38,440 --> 00:04:41,580
Remember, it's Tour.find.
98
00:04:41,580 --> 00:04:45,040
So, there's a query object and so, that's the one that
99
00:04:45,040 --> 00:04:48,010
we parsed into this class and then, of course,
100
00:04:48,010 --> 00:04:52,410
the queryString which is req.query.
101
00:04:52,410 --> 00:04:54,990
Okay, now, on this features here, remember,
102
00:04:54,990 --> 00:04:57,160
we have no access to filter.
103
00:04:57,160 --> 00:05:00,153
And so, let's actually put it right here afterwards.
104
00:05:01,410 --> 00:05:04,070
So, .filter.
105
00:05:04,070 --> 00:05:05,570
Give it a save.
106
00:05:05,570 --> 00:05:07,750
And so, just like this, we're going to run or code
107
00:05:07,750 --> 00:05:10,550
for the API filtering functionality.
108
00:05:10,550 --> 00:05:12,760
Then, here, the next line is, of course,
109
00:05:12,760 --> 00:05:14,970
not going to work because this query here
110
00:05:14,970 --> 00:05:16,670
does not anymore exist.
111
00:05:16,670 --> 00:05:20,947
Instead, what we have now is features.query, right?
112
00:05:22,760 --> 00:05:24,960
So after all this processing now, basically.
113
00:05:26,040 --> 00:05:29,530
Okay, so, right now, after this filter, this.query
114
00:05:29,530 --> 00:05:32,500
will then have this new find method on it.
115
00:05:32,500 --> 00:05:37,310
Okay, and so, again, this is then stored in this.query.
116
00:05:37,310 --> 00:05:39,910
And, later on, we will have all this other methods which,
117
00:05:39,910 --> 00:05:41,930
all of them, will manipulate this.query
118
00:05:42,886 --> 00:05:45,729
so that, in the end, this.query is the query
119
00:05:45,729 --> 00:05:47,620
that we want to execute.
120
00:05:47,620 --> 00:05:48,793
So, just like here.
121
00:05:49,920 --> 00:05:53,800
Okay, so, just like here, we always kept manipulating
122
00:05:53,800 --> 00:05:55,130
the query variable.
123
00:05:55,130 --> 00:05:57,460
We kept adding more and more methods to it
124
00:05:57,460 --> 00:06:00,100
until we, then, executed it by the end.
125
00:06:00,100 --> 00:06:02,530
And so, here, we're doing exactly the same.
126
00:06:02,530 --> 00:06:05,910
We are simply moving the code into all of these methods.
127
00:06:05,910 --> 00:06:06,743
Okay?
128
00:06:06,743 --> 00:06:09,900
Then, in the end, as I said, the query is going to be stored
129
00:06:09,900 --> 00:06:13,290
inside of this property here and so, yeah,
130
00:06:13,290 --> 00:06:14,800
that's where we, then, do the the await
131
00:06:14,800 --> 00:06:16,093
and get back the results.
132
00:06:17,360 --> 00:06:18,220
All right?
133
00:06:18,220 --> 00:06:21,763
Anyway, let's keep moving here and implement the sorting.
134
00:06:22,730 --> 00:06:24,913
So, I'm copying and commenting.
135
00:06:27,300 --> 00:06:32,003
So, filter and the next one is called Sort.
136
00:06:34,030 --> 00:06:35,160
All right.
137
00:06:35,160 --> 00:06:38,510
And so, here again, we need to replace request.query
138
00:06:38,510 --> 00:06:41,013
with this.queryString, okay.
139
00:06:43,455 --> 00:06:46,288
And then, query is now this.query.
140
00:06:47,510 --> 00:06:52,383
So let's get these four in this.query.
141
00:06:56,540 --> 00:06:59,950
Okay, now, the goal here is to basically
142
00:06:59,950 --> 00:07:03,380
chain these methods here one after another.
143
00:07:03,380 --> 00:07:05,340
So let me show that to you here.
144
00:07:05,340 --> 00:07:08,262
So we have filter and then, after that, we want to chain
145
00:07:08,262 --> 00:07:10,253
the sort method.
146
00:07:12,730 --> 00:07:15,820
Now, right now, that is not really going to work
147
00:07:15,820 --> 00:07:20,110
because where are we actually chaining this sort on?
148
00:07:20,110 --> 00:07:24,170
So, basically, we're trying to call it on the result of this
149
00:07:24,170 --> 00:07:27,120
but, right now, what is the result of this?
150
00:07:27,120 --> 00:07:29,840
Well, it's not really anything because this filter method
151
00:07:29,840 --> 00:07:32,840
here doesn't return anything, right?
152
00:07:32,840 --> 00:07:35,460
Now, this piece of code here, of course, returns
153
00:07:35,460 --> 00:07:38,830
the object that has just been created and so, then,
154
00:07:38,830 --> 00:07:41,560
we can chain the filter method on that.
155
00:07:41,560 --> 00:07:44,460
But the filter method, in turn, does not return anything.
156
00:07:44,460 --> 00:07:47,910
And so, at this point, we cannot really call a sort
157
00:07:47,910 --> 00:07:49,630
on the object, right?
158
00:07:49,630 --> 00:07:51,510
And so, the simple solution to that,
159
00:07:51,510 --> 00:07:55,033
and maybe you've done it earlier sometime in your code,
160
00:07:56,520 --> 00:07:58,853
is that we have to now return this.
161
00:08:01,120 --> 00:08:06,103
So, return this and this is simply the entire object, okay?
162
00:08:07,252 --> 00:08:09,723
And the same, then, down here.
163
00:08:11,790 --> 00:08:13,570
So, return this.
164
00:08:13,570 --> 00:08:17,360
In order to, again, return the entire object which,
165
00:08:17,360 --> 00:08:20,530
of course, then has access to these other methods
166
00:08:20,530 --> 00:08:22,493
so that we can, then, call them there.
167
00:08:23,610 --> 00:08:24,443
All right?
168
00:08:25,690 --> 00:08:28,643
So, next up is the limiting.
169
00:08:34,000 --> 00:08:36,150
And I'm going to call this one limitFields.
170
00:08:39,679 --> 00:08:41,340
And that's because all of these methods
171
00:08:41,340 --> 00:08:43,710
will have these verbs as names.
172
00:08:43,710 --> 00:08:47,240
So it's filter, sort, limit, and the paginate
173
00:08:47,240 --> 00:08:48,640
is going to be the next one.
174
00:08:49,870 --> 00:08:53,730
So, again, req.query is now this.queryString
175
00:08:57,649 --> 00:09:00,399
and query here is now this.query.
176
00:09:04,494 --> 00:09:05,327
All right?
177
00:09:08,196 --> 00:09:11,196
Return this and this is not correct.
178
00:09:14,290 --> 00:09:17,123
Okay, and finally, the pagination.
179
00:09:18,490 --> 00:09:19,873
Copy, comment.
180
00:09:25,020 --> 00:09:26,413
So, paginate.
181
00:09:29,770 --> 00:09:31,650
Return this and, of course, we need to
182
00:09:31,650 --> 00:09:34,150
replace these req.query
183
00:09:37,750 --> 00:09:39,187
this.queryString.
184
00:09:39,187 --> 00:09:41,610
And then here, just like before,
185
00:09:41,610 --> 00:09:44,890
it's going to be this.query.
186
00:09:44,890 --> 00:09:47,770
And I just realized that up there,
187
00:09:47,770 --> 00:09:51,040
right in the first method, we didn't do this here.
188
00:09:51,040 --> 00:09:54,560
So, we simply said this.query
189
00:09:54,560 --> 00:09:57,080
and then added the find there.
190
00:09:57,080 --> 00:09:59,190
But then, of course, we need to actually save it
191
00:09:59,190 --> 00:10:01,700
into this query property.
192
00:10:01,700 --> 00:10:03,593
Okay, and so, I forgot that.
193
00:10:04,650 --> 00:10:06,610
And we got some error here.
194
00:10:06,610 --> 00:10:08,280
All right, that doesn't really matter here
195
00:10:08,280 --> 00:10:09,690
at this moment.
196
00:10:09,690 --> 00:10:13,170
Or, actually, it does because this line of code here
197
00:10:13,170 --> 00:10:15,910
is actually in our paginate method.
198
00:10:15,910 --> 00:10:17,490
So let's go there.
199
00:10:17,490 --> 00:10:19,720
And, in fact, I actually wanted to talk to you
200
00:10:19,720 --> 00:10:21,210
about this here.
201
00:10:21,210 --> 00:10:24,350
Because, if you think about it, requesting the next page,
202
00:10:24,350 --> 00:10:27,740
which has zero result, is not really an error.
203
00:10:27,740 --> 00:10:30,852
The fact that there are no results is enough for the user
204
00:10:30,852 --> 00:10:34,900
to realize that, basically, the page that was requested
205
00:10:34,900 --> 00:10:36,660
doesn't contain any data.
206
00:10:36,660 --> 00:10:39,450
So we do not really need an error in this situation.
207
00:10:39,450 --> 00:10:42,933
And so, I'm just going to go ahead and delete all this code.
208
00:10:43,940 --> 00:10:45,430
Okay?
209
00:10:45,430 --> 00:10:47,600
So let me save it now here.
210
00:10:47,600 --> 00:10:49,963
And so now, of course, the error is gone.
211
00:10:53,800 --> 00:10:56,950
And here, we also still have to keep adding
212
00:10:56,950 --> 00:10:58,770
these other methods.
213
00:10:58,770 --> 00:11:02,577
So, limitFields and .paginate.
214
00:11:05,160 --> 00:11:09,360
Give it a save and, again, remember that all of this
215
00:11:09,360 --> 00:11:12,180
chaining here only works because after calling
216
00:11:12,180 --> 00:11:15,420
each of these methods, we always return this.
217
00:11:15,420 --> 00:11:18,800
And this is the object itself which has access
218
00:11:18,800 --> 00:11:21,410
to each of these methods here, making it possible
219
00:11:21,410 --> 00:11:24,640
to chain them just like we have it here.
220
00:11:24,640 --> 00:11:26,860
Okay, so, just to recap:
221
00:11:26,860 --> 00:11:31,040
We are creating a new object of the API features class.
222
00:11:31,040 --> 00:11:33,960
In there, we are parsing a query object
223
00:11:33,960 --> 00:11:37,240
and the query string that's coming from express.
224
00:11:37,240 --> 00:11:38,400
Okay?
225
00:11:38,400 --> 00:11:41,180
Then, in each of these four methods here that we call
226
00:11:41,180 --> 00:11:44,400
one after another, we, basically, manipulate the query.
227
00:11:44,400 --> 00:11:48,010
We keep adding more methods to it just like we've been doing
228
00:11:48,010 --> 00:11:52,160
up here before we did any of this refactoring, right.
229
00:11:52,160 --> 00:11:55,900
So, we keep adding stuff to the query here until the end,
230
00:11:55,900 --> 00:11:59,040
and then, by the end, we simply await the result
231
00:11:59,040 --> 00:12:02,070
that query so that it can come back with all the documents
232
00:12:02,070 --> 00:12:04,210
that were selected, okay?
233
00:12:04,210 --> 00:12:06,580
And that query now lives at features
234
00:12:06,580 --> 00:12:08,640
which is this object here.
235
00:12:08,640 --> 00:12:10,123
So features.query.
236
00:12:11,330 --> 00:12:13,620
Okay, I hope that make sense.
237
00:12:13,620 --> 00:12:17,960
So, before we do anything else, let's go back to Postman
238
00:12:17,960 --> 00:12:20,090
and actually try it out.
239
00:12:20,090 --> 00:12:23,500
And we can try it out right here with this Top-5-cheap route
240
00:12:23,500 --> 00:12:25,650
because that, actually, behind the scenes,
241
00:12:25,650 --> 00:12:29,030
uses all of these API features, right.
242
00:12:29,030 --> 00:12:32,240
So, if I send it, well, it still works.
243
00:12:32,240 --> 00:12:33,763
So that's fantastic.
244
00:12:34,730 --> 00:12:38,823
So let's close it and let me actually save it here.
245
00:12:40,490 --> 00:12:44,453
So, Get Top Five Cheap Tours.
246
00:12:49,220 --> 00:12:51,370
And yeah, I'm going to leave it there at the end.
247
00:12:51,370 --> 00:12:53,763
And now, just here, let's do some testing.
248
00:12:54,790 --> 00:12:58,373
For example, remove the sort, let me leave the limit.
249
00:12:59,570 --> 00:13:02,260
Difficulty, duration, price.
250
00:13:02,260 --> 00:13:04,170
So, I'm going to leave all of this here
251
00:13:04,170 --> 00:13:06,620
just to see if it still works.
252
00:13:06,620 --> 00:13:10,590
And it looks like everything is still working, right.
253
00:13:10,590 --> 00:13:13,110
So these are the exact same results that we got
254
00:13:13,110 --> 00:13:15,500
before our refactoring.
255
00:13:15,500 --> 00:13:17,320
So, great, perfect.
256
00:13:17,320 --> 00:13:20,530
That worked and so, let's, now, actually delete
257
00:13:20,530 --> 00:13:23,950
all this code from here which makes our route handler
258
00:13:23,950 --> 00:13:26,410
so much cleaner, doesn't it?
259
00:13:26,410 --> 00:13:30,840
So, that's so much better, really, it's day and night.
260
00:13:30,840 --> 00:13:31,800
Okay?
261
00:13:31,800 --> 00:13:34,210
Now, the next step is to actually go ahead
262
00:13:34,210 --> 00:13:38,500
and take all this code, cut it and put it into
263
00:13:38,500 --> 00:13:41,700
a new file, so a new module, basically.
264
00:13:41,700 --> 00:13:44,720
Okay, and for that, I'm going to create a new folder here
265
00:13:44,720 --> 00:13:46,563
which I'm going to call Utils.
266
00:13:47,420 --> 00:13:49,713
So that stands, basically, for utilities.
267
00:13:51,010 --> 00:13:53,850
And I'm going to add a couple of stuff in here
268
00:13:53,850 --> 00:13:55,503
over the rest of the course.
269
00:13:57,060 --> 00:13:57,893
Okay?
270
00:13:57,893 --> 00:14:00,050
So this one is going to be called
271
00:14:00,050 --> 00:14:05,050
APIFeatures.js and with a capital F here.
272
00:14:09,430 --> 00:14:10,263
All right?
273
00:14:10,263 --> 00:14:13,621
So, here goes our class and, in the end,
274
00:14:13,621 --> 00:14:17,823
we do a module.exports of this class.
275
00:14:20,040 --> 00:14:21,800
So, nothing new at this point.
276
00:14:21,800 --> 00:14:24,140
Give it a save, close it,
277
00:14:24,140 --> 00:14:27,073
and now, in here, we can require it.
278
00:14:28,147 --> 00:14:30,730
Const APIFeatures then require.
279
00:14:35,980 --> 00:14:38,490
Then we need to move one folder up,
280
00:14:38,490 --> 00:14:41,613
then into Utils and APIFeatures.
281
00:14:43,110 --> 00:14:44,210
Okay?
282
00:14:44,210 --> 00:14:45,313
One more test.
283
00:14:48,010 --> 00:14:51,000
And it's taking some time, and here we go.
284
00:14:51,000 --> 00:14:53,760
Beautiful, that's really just beautiful.
285
00:14:53,760 --> 00:14:57,720
Now, if we create another resource again,
286
00:14:57,720 --> 00:15:00,280
for example, for the users, it's going to be so easy
287
00:15:00,280 --> 00:15:02,630
to drop in this same functionality.
288
00:15:02,630 --> 00:15:06,110
All we're going to have to do is to require this file
289
00:15:06,110 --> 00:15:08,680
and then, basically, do the same as here.
290
00:15:08,680 --> 00:15:11,000
Or maybe, in that case, we don't even want
291
00:15:11,000 --> 00:15:14,040
to have this sorting ability or we don't want
292
00:15:14,040 --> 00:15:17,140
to have the filtering ability and then, all we have to do
293
00:15:17,140 --> 00:15:19,440
is to simply take out this line of code.
294
00:15:19,440 --> 00:15:21,680
And then, like magic, it'll only do
295
00:15:21,680 --> 00:15:23,280
these three functionalities
296
00:15:23,280 --> 00:15:25,810
or these three features, okay.
297
00:15:25,810 --> 00:15:27,890
And so, that's really great.
298
00:15:27,890 --> 00:15:29,630
I hope you can see the value of this
299
00:15:29,630 --> 00:15:33,353
and, yeah, I'm really happy with this result.
23140
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.