﻿1
00:00:01,280 --> 00:00:03,110
‫In this lecture, we're gonna learn

2
00:00:03,110 --> 00:00:06,660
‫about geospatial queries in order to implement

3
00:00:06,660 --> 00:00:09,147
‫a really cool feature, which is to provide

4
00:00:09,147 --> 00:00:12,750
‫a search functionality for tours within a certain

5
00:00:12,750 --> 00:00:15,313
‫distance of a specified point.

6
00:00:17,060 --> 00:00:18,712
‫So let's say you live in a certain point

7
00:00:18,712 --> 00:00:22,210
‫and wanted to know which tours start at a certain

8
00:00:22,210 --> 00:00:26,008
‫distance from you, like 250 miles, because you don't want

9
00:00:26,008 --> 00:00:28,738
‫to drive further than that in order to start your

10
00:00:28,738 --> 00:00:31,430
‫tour experience.

11
00:00:31,430 --> 00:00:33,470
‫So that would be an awesome feature,

12
00:00:33,470 --> 00:00:36,413
‫and a really nice use case of geospatial queries.

13
00:00:36,413 --> 00:00:39,804
‫And in order to implement something like this,

14
00:00:39,804 --> 00:00:43,597
‫here in our tour router, we could create a nice route,

15
00:00:43,597 --> 00:00:45,720
‫something like this.

16
00:00:45,720 --> 00:00:50,720
‫So I'm going to put it here before this general routes

17
00:00:51,810 --> 00:00:52,643
‫here.

18
00:00:54,910 --> 00:00:59,910
‫So let's say router dot route, and I'm going to call

19
00:01:00,580 --> 00:01:05,503
‫this one tours within, okay?

20
00:01:06,890 --> 00:01:09,663
‫Then we also need to specify the distance.

21
00:01:11,620 --> 00:01:14,503
‫And so therefore we create a distance parameter here.

22
00:01:15,607 --> 00:01:17,800
‫Next, we also need to specify the center,

23
00:01:17,800 --> 00:01:20,810
‫and that's basically the point where you live.

24
00:01:20,810 --> 00:01:25,810
‫So let's specify it around center and then slash,

25
00:01:27,300 --> 00:01:30,090
‫and then lat and longitude.

26
00:01:30,090 --> 00:01:31,967
‫So basically into this variable here,

27
00:01:31,967 --> 00:01:34,870
‫you want to pass in the coordinates of the place

28
00:01:34,870 --> 00:01:35,960
‫where you are.

29
00:01:35,960 --> 00:01:37,960
‫So let's say you live in Los Angeles

30
00:01:37,960 --> 00:01:40,760
‫and wanted to find all the tours within a distance

31
00:01:40,760 --> 00:01:42,390
‫of 300 miles.

32
00:01:42,390 --> 00:01:44,520
‫So here you would say 300,

33
00:01:44,520 --> 00:01:46,710
‫and then here you would put the coordinates

34
00:01:46,710 --> 00:01:49,570
‫of basically where you live, all right?

35
00:01:49,570 --> 00:01:52,610
‫Then, let's also provide the option of specifying

36
00:01:52,610 --> 00:01:53,443
‫the unit.

37
00:01:53,443 --> 00:01:57,910
‫So if this distance here is in kilometers or in miles.

38
00:01:57,910 --> 00:02:01,046
‫So let's say, slash unit,

39
00:02:01,046 --> 00:02:05,070
‫and the unit as the parameter.

40
00:02:05,070 --> 00:02:07,990
‫Now this way of specifying a URL is something

41
00:02:07,990 --> 00:02:09,364
‫that we never did before.

42
00:02:09,364 --> 00:02:12,634
‫So basically saying here center and slash

43
00:02:12,634 --> 00:02:15,521
‫and putting the longitude and latitude after that,

44
00:02:15,521 --> 00:02:17,736
‫and then slash unit,

45
00:02:17,736 --> 00:02:21,510
‫and then after that the queries parameter.

46
00:02:21,510 --> 00:02:22,832
‫And of course we could also make it so that

47
00:02:22,832 --> 00:02:25,192
‫user should specify all of these options

48
00:02:25,192 --> 00:02:28,303
‫using a query string, but this way it looks way cleaner

49
00:02:28,303 --> 00:02:33,200
‫and it's also kind of a standard way of specifying URL's

50
00:02:33,200 --> 00:02:35,554
‫which contain a lot of objects.

51
00:02:35,554 --> 00:02:39,200
‫So what I was saying that instead we could do it

52
00:02:39,200 --> 00:02:41,274
‫of course like this.

53
00:02:41,274 --> 00:02:46,274
‫Tours distance and then the user would have to provide

54
00:02:49,605 --> 00:02:51,823
‫the distance like this here.

55
00:02:53,620 --> 00:02:57,179
‫And the center like this, let's say minus 40,

56
00:02:57,179 --> 00:03:02,179
‫and 45, and then the unit also sets to miles.

57
00:03:04,090 --> 00:03:07,121
‫Okay, so this has been one way using query strings

58
00:03:07,121 --> 00:03:09,343
‫and we have done it before.

59
00:03:09,343 --> 00:03:14,100
‫And actually not like this, but like this.

60
00:03:14,100 --> 00:03:16,740
‫Okay, but instead we are going to specify

61
00:03:16,740 --> 00:03:19,063
‫it again like this.

62
00:03:20,990 --> 00:03:23,303
‫Which in my opinion looks way nicer.

63
00:03:26,040 --> 00:03:28,217
‫So minus 40, 45.

64
00:03:31,650 --> 00:03:33,905
‫Okay, so think that this here really looks a lot

65
00:03:33,905 --> 00:03:36,610
‫cleaner than this.

66
00:03:36,610 --> 00:03:39,290
‫Okay, and so this is another thing that I wanted

67
00:03:39,290 --> 00:03:41,249
‫to show you is that it's kind of a standard of

68
00:03:41,249 --> 00:03:45,750
‫specifying URL's like this, all right?

69
00:03:45,750 --> 00:03:46,971
‫Anyways, for this route of course,

70
00:03:46,971 --> 00:03:49,753
‫we need a route handler, and that's gonna be at

71
00:03:49,753 --> 00:03:52,100
‫tour controller, and let's call this handler function

72
00:03:52,100 --> 00:03:57,100
‫get tours within.

73
00:03:59,530 --> 00:04:02,775
‫And so let's now go ahead and implement this method

74
00:04:02,775 --> 00:04:04,513
‫to this handler.

75
00:04:06,280 --> 00:04:10,660
‫So tour controller and right down here.

76
00:04:17,970 --> 00:04:20,239
‫And let's start by getting all parameters.

77
00:04:20,239 --> 00:04:24,253
‫So let me just copy all of this here.

78
00:04:25,667 --> 00:04:28,833
‫And just so we know what our data looks like.

79
00:04:29,810 --> 00:04:30,643
‫All right?

80
00:04:32,570 --> 00:04:35,953
‫So this, and then this has a comment.

81
00:04:42,550 --> 00:04:47,069
‫All right, so let's use a simple restructuring

82
00:04:47,069 --> 00:04:51,186
‫to get all our data at once from the parameters.

83
00:04:51,186 --> 00:04:54,477
‫And actually we need to say const,

84
00:04:54,477 --> 00:04:59,477
‫and distance, and unit.

85
00:05:01,650 --> 00:05:05,323
‫So all of that comes from request dot params.

86
00:05:08,402 --> 00:05:11,320
‫Okay, so on req.params, we have dot distance,

87
00:05:11,320 --> 00:05:13,990
‫dot center, and dot unit, right?

88
00:05:13,990 --> 00:05:16,122
‫Because these are the names of the three parameters

89
00:05:16,122 --> 00:05:18,510
‫that we specified here.

90
00:05:18,510 --> 00:05:19,950
‫And actually it's not center,

91
00:05:19,950 --> 00:05:23,448
‫it's latlng here, okay, so that's the correct one,

92
00:05:23,448 --> 00:05:27,440
‫and then finally the unit.

93
00:05:27,440 --> 00:05:30,190
‫So again, we use restructuring to get all these

94
00:05:30,190 --> 00:05:31,703
‫variables at once.

95
00:05:33,438 --> 00:05:35,880
‫Next up, let's actually get all coordinates from this

96
00:05:35,880 --> 00:05:38,730
‫latitude longitude variable here.

97
00:05:38,730 --> 00:05:42,826
‫So as we see, we expect the data in the format like this,

98
00:05:42,826 --> 00:05:45,930
‫and so that makes it really easy to copy this data

99
00:05:45,930 --> 00:05:47,610
‫from Google Maps.

100
00:05:47,610 --> 00:05:49,610
‫So let me just quickly show that to you.

101
00:05:50,573 --> 00:05:53,310
‫It's important that you understand how this kind of stuff

102
00:05:53,310 --> 00:05:55,563
‫also works in practice.

103
00:05:59,380 --> 00:06:03,323
‫So let's use the Los Angeles example here.

104
00:06:07,430 --> 00:06:10,593
‫Okay, and so let's say you live somewhere here.

105
00:06:12,720 --> 00:06:17,350
‫Okay, and so you can very easily get the latitude

106
00:06:17,350 --> 00:06:20,124
‫and the longitude like this, okay?

107
00:06:20,124 --> 00:06:24,523
‫So put that here, just as an example again.

108
00:06:26,140 --> 00:06:27,840
‫And so this is the format.

109
00:06:27,840 --> 00:06:30,483
‫It looks like latitude and longitude.

110
00:06:32,610 --> 00:06:36,263
‫And so let's now create one variable for each of them.

111
00:06:37,755 --> 00:06:39,170
‫So one for latitude and one for longitude.

112
00:06:39,170 --> 00:06:44,170
‫So lat longitude dot split because it's a string

113
00:06:45,074 --> 00:06:48,940
‫and we want to split it by comma.

114
00:06:48,940 --> 00:06:51,577
‫And so that will then create an array of two elements,

115
00:06:51,577 --> 00:06:55,180
‫and now we can again use destructering in order to save

116
00:06:55,180 --> 00:06:58,193
‫these to the two variables that we're interested in.

117
00:07:01,910 --> 00:07:05,073
‫So latitude and longitude.

118
00:07:12,110 --> 00:07:15,200
‫Okay, next up, I want to test if we actually have

119
00:07:15,200 --> 00:07:17,810
‫the longitude and latitude variables to find.

120
00:07:17,810 --> 00:07:20,940
‫Because if not, then it means the user didn't specify

121
00:07:20,940 --> 00:07:23,040
‫them in the required format.

122
00:07:23,040 --> 00:07:25,270
‫So let's say if there is no latitude,

123
00:07:25,270 --> 00:07:30,270
‫or no longitude, then we want to create a new error.

124
00:07:32,610 --> 00:07:37,610
‫So as always, new app error, and I'm not sure

125
00:07:39,520 --> 00:07:42,590
‫if we have it actually still, right here,

126
00:07:42,590 --> 00:07:43,825
‫and actually we don't.

127
00:07:43,825 --> 00:07:47,270
‫So we commented out this part because we no longer

128
00:07:47,270 --> 00:07:50,240
‫needed the app error after creating our handler

129
00:07:50,240 --> 00:07:53,610
‫factory functions, but now, we actually need it again,

130
00:07:53,610 --> 00:07:55,003
‫and so let's bring it back.

131
00:07:58,476 --> 00:08:00,876
‫And the message here is gonna be please provide,

132
00:08:06,510 --> 00:08:11,303
‫in the format, like this.

133
00:08:12,400 --> 00:08:15,463
‫And error code 400 for that request.

134
00:08:17,230 --> 00:08:21,657
‫Great, and now just to see if all of this is

135
00:08:21,657 --> 00:08:23,220
‫working correctly,

136
00:08:23,220 --> 00:08:27,490
‫let's just log out of this to the console.

137
00:08:27,490 --> 00:08:32,490
‫The distance that longitude and unit.

138
00:08:36,050 --> 00:08:39,113
‫And let's also send a generic message here,

139
00:08:40,910 --> 00:08:44,273
‫just to really finish the request to respond cycle.

140
00:08:45,240 --> 00:08:48,253
‫And for that of course is the same as always.

141
00:08:52,368 --> 00:08:54,950
‫So status success for now, and the of course later on

142
00:08:54,950 --> 00:08:57,523
‫we will send the data that the query returns.

143
00:08:59,930 --> 00:09:01,823
‫So actually let's copy this here.

144
00:09:03,360 --> 00:09:05,610
‫Because this kind of is already what we want.

145
00:09:08,080 --> 00:09:13,060
‫So back in Postman, let's close all of this.

146
00:09:13,060 --> 00:09:14,563
‫This one we no longer need.

147
00:09:18,720 --> 00:09:21,620
‫All right, we also don't need to be logged in,

148
00:09:21,620 --> 00:09:23,883
‫and we also don't want any updates.

149
00:09:26,952 --> 00:09:30,800
‫So anyway, we also need to get this part

150
00:09:30,800 --> 00:09:33,379
‫which I'm too lazy to write out.

151
00:09:33,379 --> 00:09:38,379
‫And so let's test that now.

152
00:09:39,800 --> 00:09:41,410
‫And that didn't work,

153
00:09:41,410 --> 00:09:45,033
‫and I think this one we called tours within actually.

154
00:09:46,035 --> 00:09:46,868
‫Did we?

155
00:09:47,830 --> 00:09:49,640
‫So tours within.

156
00:09:49,640 --> 00:09:53,065
‫So I'm not sure why I wrote distance here

157
00:09:53,065 --> 00:09:58,065
‫let's just quickly fix that here in our examples.

158
00:10:00,800 --> 00:10:03,513
‫And so of course it's tours within.

159
00:10:06,120 --> 00:10:10,057
‫And that's still not working, so let's take a look

160
00:10:10,057 --> 00:10:12,007
‫and route implementation here actually.

161
00:10:15,510 --> 00:10:17,993
‫So here we have that, and yes of course,

162
00:10:17,993 --> 00:10:21,156
‫this is not correct at all.

163
00:10:21,156 --> 00:10:26,156
‫So this one here should not be inside dot route, obviously.

164
00:10:26,450 --> 00:10:29,363
‫But instead, it should be in the get method.

165
00:10:34,030 --> 00:10:36,820
‫And so now that looks a lot more like what

166
00:10:36,820 --> 00:10:37,860
‫we have here.

167
00:10:37,860 --> 00:10:40,163
‫So dot route and then dot get.

168
00:10:42,910 --> 00:10:45,963
‫So one less try and this time it worked.

169
00:10:46,800 --> 00:10:49,200
‫And let's take a look at the console,

170
00:10:49,200 --> 00:10:51,634
‫and indeed, here we get distance that is specified

171
00:10:51,634 --> 00:10:56,450
‫the latitude to longitude, and the unit.

172
00:10:56,450 --> 00:10:58,690
‫Great, and so now it's time to actually write

173
00:10:58,690 --> 00:11:00,673
‫the query itself.

174
00:11:01,610 --> 00:11:04,112
‫Now a geospatial query actually works quite similar

175
00:11:04,112 --> 00:11:06,830
‫to a regular query.

176
00:11:06,830 --> 00:11:10,677
‫So we're still going to write tours is equal to tour.find,

177
00:11:17,400 --> 00:11:21,833
‫and of course, awaiting the result of this promise.

178
00:11:24,720 --> 00:11:28,120
‫And then the old game of marking everything

179
00:11:28,120 --> 00:11:33,120
‫as async and then catch the async and wrap our function

180
00:11:34,890 --> 00:11:35,723
‫in there.

181
00:11:37,910 --> 00:11:40,280
‫So we have all tours here unused,

182
00:11:40,280 --> 00:11:44,266
‫and so let's go ahead and edit to the response object

183
00:11:44,266 --> 00:11:46,240
‫right away.

184
00:11:46,240 --> 00:11:51,120
‫So data, and now remember how we called it data.

185
00:11:52,610 --> 00:11:54,803
‫And then tours.

186
00:11:58,970 --> 00:12:01,293
‫Okay, and all we need to do is to specify

187
00:12:01,293 --> 00:12:03,193
‫or filter object here.

188
00:12:04,660 --> 00:12:06,770
‫So remember that we want to basically

189
00:12:06,770 --> 00:12:09,010
‫query for start location,

190
00:12:09,010 --> 00:12:11,316
‫because the start location field is what holds

191
00:12:11,316 --> 00:12:15,240
‫the geospatial point where each tour starts.

192
00:12:15,240 --> 00:12:17,683
‫And so that's exactly what we're searching for.

193
00:12:18,890 --> 00:12:23,023
‫So, start location, and now we need to specify

194
00:12:23,023 --> 00:12:25,900
‫the value that we're searching for.

195
00:12:25,900 --> 00:12:28,389
‫And for that, we will now use a geospatial operator

196
00:12:28,389 --> 00:12:30,203
‫called geo within.

197
00:12:31,920 --> 00:12:34,120
‫As always, we need to specify the subject,

198
00:12:34,120 --> 00:12:36,900
‫and then here, where we would earlier use like some

199
00:12:36,900 --> 00:12:39,860
‫math operator like greater than,

200
00:12:39,860 --> 00:12:44,163
‫this time we use a geospatial operator like this one.

201
00:12:45,640 --> 00:12:49,950
‫Geo within, and this operator does exactly what it says.

202
00:12:49,950 --> 00:12:53,740
‫Basically it finds documents within a certain geometry.

203
00:12:53,740 --> 00:12:58,040
‫And that geometry is what we need to define as a next step.

204
00:12:58,040 --> 00:12:59,600
‫So we want to find documents,

205
00:12:59,600 --> 00:13:03,440
‫but where do we actually want to find these documents?

206
00:13:03,440 --> 00:13:06,792
‫Well we want to find them inside of a sphere that starts

207
00:13:06,792 --> 00:13:09,780
‫at this point that we defined,

208
00:13:09,780 --> 00:13:13,680
‫and which has a radius of the distance that we defined.

209
00:13:13,680 --> 00:13:16,023
‫So again with our example in Los Angeles,

210
00:13:17,029 --> 00:13:18,646
‫if you specify the distance of 250 miles,

211
00:13:18,646 --> 00:13:21,660
‫then that means you want to find all the tour documents

212
00:13:21,660 --> 00:13:26,150
‫within a sphere that has a radius of 250 miles.

213
00:13:26,150 --> 00:13:28,190
‫Okay, make sense?

214
00:13:28,190 --> 00:13:30,313
‫And so now we need to pass the information here

215
00:13:30,313 --> 00:13:33,810
‫into the geo within operator, okay?

216
00:13:33,810 --> 00:13:36,563
‫And we do that by defining a center sphere.

217
00:13:40,160 --> 00:13:42,793
‫Okay, and again, I know that this looks quite confusing,

218
00:13:42,793 --> 00:13:47,380
‫but that's why I'm explaining it here step by step.

219
00:13:47,380 --> 00:13:49,150
‫And also in a second, we're going to take a look

220
00:13:49,150 --> 00:13:51,080
‫at the documentation.

221
00:13:51,080 --> 00:13:53,307
‫So the center sphere operator takes an array

222
00:13:53,307 --> 00:13:56,900
‫of the coordinates and of the radius.

223
00:13:56,900 --> 00:13:59,501
‫And let's actually format the code here to at least

224
00:13:59,501 --> 00:14:02,770
‫make it look a bit easier, okay?

225
00:14:02,770 --> 00:14:05,558
‫Well it kind of looks the same, but anyway,

226
00:14:05,558 --> 00:14:08,020
‫that's how you find the coordinates here.

227
00:14:08,020 --> 00:14:10,900
‫And for that, we need yet another array,

228
00:14:10,900 --> 00:14:14,890
‫and then the longitude and the latitude.

229
00:14:14,890 --> 00:14:15,723
‫And that's right.

230
00:14:15,723 --> 00:14:17,984
‫You first need to always define the longitude

231
00:14:17,984 --> 00:14:21,040
‫and then the latitude, which is a bit counterintuitive

232
00:14:21,040 --> 00:14:24,366
‫because usually coordinate pairs are always specified

233
00:14:24,366 --> 00:14:27,760
‫with the latitude first, and the longitude first.

234
00:14:27,760 --> 00:14:30,298
‫I think I mentioned it before that in geo adjacent,

235
00:14:30,298 --> 00:14:33,590
‫it for some reason works like this.

236
00:14:33,590 --> 00:14:35,430
‫So that is the center of the sphere.

237
00:14:35,430 --> 00:14:36,263
‫Now we need to specify it's radius.

238
00:14:36,263 --> 00:14:41,130
‫Now here we actually do not pass in the distance,

239
00:14:41,130 --> 00:14:45,100
‫but instead it expects a radius in a special unit

240
00:14:45,100 --> 00:14:46,600
‫called radians.

241
00:14:46,600 --> 00:14:48,780
‫So let me put radius variable here,

242
00:14:48,780 --> 00:14:51,633
‫and then in a second we are going to define it.

243
00:14:56,190 --> 00:15:00,820
‫So let's now actually define the radius.

244
00:15:00,820 --> 00:15:03,780
‫So again, the radius is basically the distance

245
00:15:03,780 --> 00:15:06,000
‫that we want to have as the radius,

246
00:15:06,000 --> 00:15:09,500
‫but converted to a special unit called radians.

247
00:15:09,500 --> 00:15:11,441
‫And in order to get the radians,

248
00:15:11,441 --> 00:15:14,217
‫we need to divide our distance by the radius

249
00:15:14,217 --> 00:15:15,940
‫of the earth.

250
00:15:15,940 --> 00:15:20,340
‫So that sounds a bit crazy but really this is how it works.

251
00:15:20,340 --> 00:15:23,532
‫Okay, so now we actually need to take into consideration

252
00:15:23,532 --> 00:15:27,313
‫our units here, because of course the radius of the earth

253
00:15:27,313 --> 00:15:31,180
‫is different in miles then in kilometers.

254
00:15:31,180 --> 00:15:33,756
‫So let's now do a turnery of greater here

255
00:15:33,756 --> 00:15:38,756
‫and say that if the unit is equal to miles,

256
00:15:40,074 --> 00:15:43,453
‫well then the result here should be distance.

257
00:15:44,510 --> 00:15:49,290
‫So basically our original radius divided by 3963.2.

258
00:15:52,930 --> 00:15:55,383
‫Okay, so again, that is the radius of the Earth in miles.

259
00:15:55,383 --> 00:15:59,217
‫Okay, and otherwise,

260
00:15:59,217 --> 00:16:01,663
‫we will then assume that it's kilometer.

261
00:16:01,663 --> 00:16:05,941
‫And so if it is kilometers, then it is the distance

262
00:16:05,941 --> 00:16:10,157
‫divided by 6,378.1 kilometers.

263
00:16:14,210 --> 00:16:19,210
‫All right, so again, this kind of crazy conversion here

264
00:16:19,900 --> 00:16:21,819
‫is necessary because normally it would expect

265
00:16:21,819 --> 00:16:26,117
‫the radius of our sphere to be in radians.

266
00:16:26,117 --> 00:16:28,292
‫And radians we get by dividing the distance

267
00:16:28,292 --> 00:16:30,593
‫by the radius of the Earth.

268
00:16:31,450 --> 00:16:34,173
‫Great, so we're almost ready to test this now.

269
00:16:34,173 --> 00:16:39,173
‫Let's just add the results property that we used to have.

270
00:16:43,530 --> 00:16:46,060
‫So with the number of results basically,

271
00:16:46,060 --> 00:16:48,057
‫and then another very important thing

272
00:16:48,057 --> 00:16:50,918
‫is that we actually in order to be able to do just

273
00:16:50,918 --> 00:16:54,845
‫basic queries, we need to first attribute an index

274
00:16:54,845 --> 00:16:57,664
‫to the field where the geospatial data

275
00:16:57,664 --> 00:17:01,440
‫that we're searching for is stored.

276
00:17:01,440 --> 00:17:05,700
‫So in this case, we need to add an index to start location.

277
00:17:05,700 --> 00:17:08,503
‫So let's do that here in tour model.

278
00:17:10,310 --> 00:17:14,820
‫So down here, we need yet another index.

279
00:17:14,820 --> 00:17:17,853
‫Tour schema.index.

280
00:17:19,185 --> 00:17:24,185
‫Start location, but now we're actually not going

281
00:17:26,070 --> 00:17:28,530
‫to set it to one or minus one,

282
00:17:28,530 --> 00:17:30,750
‫because this time it is a different index

283
00:17:30,750 --> 00:17:31,940
‫that we need.

284
00:17:31,940 --> 00:17:35,045
‫So for geospatial data, this index needs to be a

285
00:17:35,045 --> 00:17:39,160
‫2D sphere index if the data describes real points

286
00:17:39,160 --> 00:17:41,314
‫on the Earth like sphere.

287
00:17:41,314 --> 00:17:45,276
‫Or instead, we can also use a 2D index if we're using

288
00:17:45,276 --> 00:17:49,660
‫just fictional points on a simple two dimensional plane.

289
00:17:49,660 --> 00:17:52,210
‫Now in this case of course, we are talking about real

290
00:17:52,210 --> 00:17:54,411
‫points on the Earth's surface,

291
00:17:54,411 --> 00:17:58,805
‫so we're going to use a 2D sphere index here.

292
00:17:58,805 --> 00:18:03,805
‫So a 2D sphere like this.

293
00:18:04,000 --> 00:18:07,253
‫Okay, and so we're basically telling that this start

294
00:18:07,253 --> 00:18:12,090
‫location here should be indexed to a 2D sphere.

295
00:18:12,090 --> 00:18:16,510
‫So an Earthlike sphere where all our data are located.

296
00:18:16,510 --> 00:18:18,906
‫Great, and with that, we should now actually be ready

297
00:18:18,906 --> 00:18:22,283
‫to test out our new route.

298
00:18:23,520 --> 00:18:26,839
‫Okay, let's just increase this radius here a little bit

299
00:18:26,839 --> 00:18:31,839
‫by 400 miles, and so let's see what we get.

300
00:18:32,260 --> 00:18:34,609
‫Well, we get this weird looking error,

301
00:18:34,609 --> 00:18:37,282
‫and I'm not really sure what that is.

302
00:18:37,282 --> 00:18:40,290
‫And so, let's take a look.

303
00:18:40,290 --> 00:18:43,330
‫And probably it's something wrong here with the radius,

304
00:18:43,330 --> 00:18:46,810
‫but actually this is a great time to test out our debugger.

305
00:18:46,810 --> 00:18:49,130
‫So I showed that to you a long time ago,

306
00:18:49,130 --> 00:18:51,700
‫but this is a good use case for actually taking a look

307
00:18:51,700 --> 00:18:53,743
‫at the debugger again.

308
00:18:54,950 --> 00:18:57,620
‫So I think we have a NPM script for that,

309
00:18:57,620 --> 00:18:59,140
‫it's called debug.

310
00:18:59,140 --> 00:19:04,140
‫So we need to know this process, and then say NPM run debug.

311
00:19:07,460 --> 00:19:08,293
‫Okay?

312
00:19:09,570 --> 00:19:12,818
‫So that should open up this nice window.

313
00:19:12,818 --> 00:19:17,233
‫And let's close up all of these files here.

314
00:19:18,560 --> 00:19:21,898
‫Okay, and so we're in our controllers.

315
00:19:21,898 --> 00:19:23,673
‫Tour controller.

316
00:19:24,680 --> 00:19:29,590
‫And so now, let's set a break point right here.

317
00:19:29,590 --> 00:19:31,940
‫Okay, because at this point, we will have all our

318
00:19:31,940 --> 00:19:33,998
‫variables defined, and so we can then take a look

319
00:19:33,998 --> 00:19:38,480
‫at their values in order to see what's going on.

320
00:19:38,480 --> 00:19:40,877
‫So of course we could of done that with a simple

321
00:19:40,877 --> 00:19:43,343
‫console.log, but in some situations where you have

322
00:19:43,343 --> 00:19:45,544
‫a lot of stuff going on,

323
00:19:45,544 --> 00:19:48,399
‫and it's also nice to use the debugger.

324
00:19:48,399 --> 00:19:50,777
‫So we need to send our request.

325
00:19:50,777 --> 00:19:54,750
‫And now we're in the debugger at our break point.

326
00:19:54,750 --> 00:19:56,240
‫And so at this point in time,

327
00:19:56,240 --> 00:19:58,280
‫our code has really stopped.

328
00:19:58,280 --> 00:20:00,187
‫And we can see here that actually all our variables

329
00:20:00,187 --> 00:20:02,953
‫seem to be defined.

330
00:20:04,130 --> 00:20:07,280
‫Let's take a look at that here in local.

331
00:20:07,280 --> 00:20:09,153
‫So we have a distance, we have the latitude,

332
00:20:09,153 --> 00:20:13,360
‫the longitude, and also the radius.

333
00:20:13,360 --> 00:20:14,916
‫So let's keep going here.

334
00:20:14,916 --> 00:20:16,493
‫So we jumped right to then next line because this if

335
00:20:16,493 --> 00:20:21,493
‫here didn't enter the if block.

336
00:20:24,350 --> 00:20:27,400
‫And so now it's running all of these functions.

337
00:20:27,400 --> 00:20:29,600
‫But let's step out of them actually,

338
00:20:29,600 --> 00:20:32,680
‫and now we actually get tours undefined.

339
00:20:32,680 --> 00:20:36,010
‫So if we now continue this, we will probably get

340
00:20:36,010 --> 00:20:40,690
‫that same error again, right?

341
00:20:40,690 --> 00:20:43,160
‫And so indeed, we do.

342
00:20:43,160 --> 00:20:46,043
‫So it must be something here in this line, let's say,

343
00:20:46,043 --> 00:20:50,894
‫and indeed, I think I found the error.

344
00:20:50,894 --> 00:20:53,820
‫So that's now how you write sphere.

345
00:20:53,820 --> 00:20:57,096
‫So sphere is more like this, right?

346
00:20:57,096 --> 00:21:01,963
‫So I hope and I believe that actually this was the error.

347
00:21:04,100 --> 00:21:07,390
‫So let's actually close up the debugger here,

348
00:21:07,390 --> 00:21:10,718
‫and let's relieve, and actually that should of

349
00:21:10,718 --> 00:21:12,593
‫updated my code here.

350
00:21:13,690 --> 00:21:15,913
‫Let's see, and it actually didn't.

351
00:21:17,180 --> 00:21:21,980
‫I'm not sure why that is, but all right.

352
00:21:21,980 --> 00:21:23,373
‫Let's run this here again.

353
00:21:24,230 --> 00:21:27,350
‫Not this command, okay anyway,

354
00:21:27,350 --> 00:21:30,623
‫let's just do NPM start.

355
00:21:34,210 --> 00:21:35,463
‫Close all of these.

356
00:21:36,970 --> 00:21:38,293
‫And now try it again.

357
00:21:40,500 --> 00:21:44,080
‫Ah, and now we get some real results here, nice.

358
00:21:44,080 --> 00:21:47,800
‫So it tells me that these tours here are in that

359
00:21:47,800 --> 00:21:51,170
‫400 mile distance that is specified.

360
00:21:51,170 --> 00:21:54,550
‫But how can we really know that it's true?

361
00:21:54,550 --> 00:21:57,827
‫Well actually we can use compass for this.

362
00:21:57,827 --> 00:22:01,784
‫So if we open up compass here, we have something really nice

363
00:22:01,784 --> 00:22:04,090
‫which is this schema.

364
00:22:04,090 --> 00:22:06,660
‫So let's do that here in the tours.

365
00:22:06,660 --> 00:22:09,818
‫And so we can now come to schema here

366
00:22:09,818 --> 00:22:11,773
‫and then analyze this schema.

367
00:22:12,830 --> 00:22:15,456
‫So analyze the schema, and so now here we have a nice

368
00:22:15,456 --> 00:22:17,893
‫summary for all of our fields.

369
00:22:19,648 --> 00:22:20,893
‫For example you see that the difficulty

370
00:22:20,893 --> 00:22:23,477
‫is easy in 50% of the documents,

371
00:22:23,477 --> 00:22:28,477
‫medium in 30%, and difficult in 20%.

372
00:22:28,480 --> 00:22:29,990
‫You also see these durations.

373
00:22:29,990 --> 00:22:34,880
‫So in 20% it's five, and also nine is also more popular

374
00:22:34,880 --> 00:22:36,643
‫than the other durations.

375
00:22:38,030 --> 00:22:41,491
‫Now what I'm really interested in here is the locations.

376
00:22:41,491 --> 00:22:46,283
‫Or actually the start locations, so that's here.

377
00:22:47,400 --> 00:22:49,801
‫And now normally, you would see a map here.

378
00:22:49,801 --> 00:22:53,217
‫But right now, there is no map because we have

379
00:22:53,217 --> 00:22:56,816
‫a document right now which doesn't have a start location.

380
00:22:56,816 --> 00:22:58,648
‫So in order for this to work properly,

381
00:22:58,648 --> 00:23:02,616
‫we need to get rid of that document.

382
00:23:02,616 --> 00:23:05,046
‫So it was one of these testing documents

383
00:23:05,046 --> 00:23:08,994
‫that we created, but which we now actually no longer need.

384
00:23:08,994 --> 00:23:12,330
‫So let me see if it shows up here.

385
00:23:12,330 --> 00:23:14,065
‫Maybe it's in the end.

386
00:23:14,065 --> 00:23:16,452
‫So yeah, it's this new test tour.

387
00:23:16,452 --> 00:23:19,681
‫Let's get rid of that.

388
00:23:19,681 --> 00:23:23,310
‫Back to our schema, let's analyze it again.

389
00:23:23,310 --> 00:23:28,310
‫Okay, so here we have the star applications.

390
00:23:31,650 --> 00:23:35,760
‫And here you already see the map, so that's great, right?

391
00:23:35,760 --> 00:23:38,660
‫That's really really a handy feature.

392
00:23:38,660 --> 00:23:40,485
‫So we should have nine points here.

393
00:23:40,485 --> 00:23:44,880
‫So one, two, three, four, five, six, seven, eight,

394
00:23:44,880 --> 00:23:47,240
‫one up here, the ninth one.

395
00:23:47,240 --> 00:23:50,313
‫So probably this one is to see the Northern Lights.

396
00:23:50,313 --> 00:23:51,940
‫Right?

397
00:23:51,940 --> 00:23:54,880
‫And now here we can actually replicate that query

398
00:23:54,880 --> 00:23:56,583
‫using this graphical interface.

399
00:23:57,780 --> 00:24:00,960
‫So let's come to Los Angeles and approximately

400
00:24:00,960 --> 00:24:03,210
‫to the point where we were.

401
00:24:03,210 --> 00:24:05,920
‫So let's say here, and I'm zooming out a little bit

402
00:24:05,920 --> 00:24:07,840
‫just to give some more space,

403
00:24:07,840 --> 00:24:11,120
‫but now we can hit shift and then drag.

404
00:24:11,120 --> 00:24:12,783
‫So just as it says down here.

405
00:24:13,810 --> 00:24:16,340
‫So put the hand where our point was,

406
00:24:16,340 --> 00:24:18,727
‫so basically somewhere here in Los Angeles.

407
00:24:18,727 --> 00:24:22,750
‫Now shift, and then drag, now all right.

408
00:24:22,750 --> 00:24:25,410
‫And so you can see that as we start increasing

409
00:24:25,410 --> 00:24:28,132
‫this sphere, we get more and more towards

410
00:24:28,132 --> 00:24:32,053
‫some more of these points here turning yellow, okay?

411
00:24:32,053 --> 00:24:37,053
‫And I believed that our radius was something like 0.1,

412
00:24:37,232 --> 00:24:42,232
‫or something like this, let's say.

413
00:24:42,320 --> 00:24:45,540
‫And so you see that actually three documents,

414
00:24:45,540 --> 00:24:48,740
‫so three tours all within this sphere

415
00:24:48,740 --> 00:24:51,010
‫that we just created, okay?

416
00:24:51,010 --> 00:24:54,380
‫So we have this sphere with the radius of 0.1,

417
00:24:54,380 --> 00:24:56,060
‫as you can see up here.

418
00:24:56,060 --> 00:24:58,583
‫And so in fact this query looks just like the one

419
00:24:58,583 --> 00:25:02,260
‫that we just filled with code in our controller function,

420
00:25:02,260 --> 00:25:03,218
‫right?

421
00:25:03,218 --> 00:25:07,500
‫So we get these three documents that are marked

422
00:25:07,500 --> 00:25:12,177
‫as orange, so let's actually now hit analyze here again,

423
00:25:12,177 --> 00:25:15,853
‫and so now our query returned three documents.

424
00:25:17,100 --> 00:25:19,920
‫So let's see the names actually.

425
00:25:19,920 --> 00:25:21,731
‫So where is that?

426
00:25:21,731 --> 00:25:24,171
‫For the sports lover, the wine taster,

427
00:25:24,171 --> 00:25:26,130
‫and the park camper.

428
00:25:26,130 --> 00:25:28,670
‫And the three tours that we got in Postman,

429
00:25:28,670 --> 00:25:32,440
‫so as a result for API, should be these exact same three.

430
00:25:32,440 --> 00:25:35,743
‫So the sports lover, wine taster, and park camper.

431
00:25:39,440 --> 00:25:43,853
‫So park camper, then you have,

432
00:25:45,806 --> 00:25:47,643
‫the sports lover,

433
00:25:51,168 --> 00:25:54,420
‫and the last one remember should be the wine taster,

434
00:25:54,420 --> 00:25:56,450
‫and indeed it is.

435
00:25:56,450 --> 00:25:58,467
‫Great, that's really fantastic.

436
00:25:58,467 --> 00:26:02,706
‫Let's now just decrease this here to 200,

437
00:26:02,706 --> 00:26:06,214
‫let's see how many results you get then,

438
00:26:06,214 --> 00:26:09,293
‫and in fact it's only just one.

439
00:26:10,150 --> 00:26:12,635
‫So let's come back to compass here.

440
00:26:12,635 --> 00:26:16,510
‫Let's delete this query here.

441
00:26:16,510 --> 00:26:19,159
‫So if we get back to all our documents,

442
00:26:19,159 --> 00:26:21,473
‫take a look at our map.

443
00:26:23,200 --> 00:26:28,150
‫And so here is LA, okay.

444
00:26:28,150 --> 00:26:30,803
‫It's another radius should be something like 0.05.

445
00:26:31,861 --> 00:26:34,970
‫Now something like this, let's say,

446
00:26:34,970 --> 00:26:38,125
‫and so indeed we only get this one tour which I believe

447
00:26:38,125 --> 00:26:42,209
‫is the wine taster or something.

448
00:26:42,209 --> 00:26:44,184
‫Yeah, we have to analyze this.

449
00:26:44,184 --> 00:26:49,184
‫So oh, actually it's the sports lover.

450
00:26:51,650 --> 00:26:54,233
‫And so let's see if that's what we got here.

451
00:26:56,210 --> 00:26:57,800
‫And indeed, it is.

452
00:26:57,800 --> 00:27:00,211
‫So it's the sports lover, and so that is the only tour

453
00:27:00,211 --> 00:27:04,910
‫that is within 200 miles of Los Angeles.

454
00:27:04,910 --> 00:27:06,000
‫Fantastic.

455
00:27:06,000 --> 00:27:09,883
‫So this I find really really exciting, really cool.

456
00:27:11,860 --> 00:27:14,036
‫Let me just show you another thing very quickly,

457
00:27:14,036 --> 00:27:18,303
‫so you can also see all of our locations on the map.

458
00:27:19,200 --> 00:27:20,823
‫So that's here.

459
00:27:22,800 --> 00:27:25,818
‫And so these are the locations of all of the tours,

460
00:27:25,818 --> 00:27:30,280
‫so the ones that are stored in location.

461
00:27:30,280 --> 00:27:32,830
‫So we have the coordinates, and we also have days,

462
00:27:32,830 --> 00:27:35,293
‫descriptions, and the time, okay?

463
00:27:38,067 --> 00:27:41,266
‫And of course our query is not about all of this here.

464
00:27:41,266 --> 00:27:43,516
‫For that query we really just care about the

465
00:27:43,516 --> 00:27:46,583
‫star locations, but I still wanted to show you this map

466
00:27:46,583 --> 00:27:50,890
‫where we can actually see all of the locations as well.

467
00:27:50,890 --> 00:27:54,251
‫Okay, so there really is a huge potential for using

468
00:27:54,251 --> 00:27:56,770
‫geospatial data with MongoDB.

469
00:27:56,770 --> 00:27:59,870
‫The possibilities are really endless for doing

470
00:27:59,870 --> 00:28:02,010
‫geospatial queries like this.

471
00:28:02,010 --> 00:28:03,735
‫And I actually wanted to show you if we have some more

472
00:28:03,735 --> 00:28:06,637
‫geospatial operators in MongoDB.

473
00:28:06,637 --> 00:28:10,603
‫So let's take a look at the documentation here again.

474
00:28:11,931 --> 00:28:14,569
‫So let's come down here again to the reference

475
00:28:14,569 --> 00:28:19,569
‫and operators, and query operators.

476
00:28:21,970 --> 00:28:25,530
‫And I think it's somewhere down here, yeah.

477
00:28:25,530 --> 00:28:27,583
‫So here we have the geospatial operator.

478
00:28:27,583 --> 00:28:31,020
‫And you see that this is the one that we used,

479
00:28:31,020 --> 00:28:33,599
‫so the one that selects geometries within a bounding

480
00:28:33,599 --> 00:28:36,190
‫geo adjacent geometry.

481
00:28:36,190 --> 00:28:39,220
‫That sounds a bit weird, but this bounding

482
00:28:39,220 --> 00:28:42,546
‫geo adjacent geometry is that sphere that we defined

483
00:28:42,546 --> 00:28:44,570
‫in our code, right?

484
00:28:44,570 --> 00:28:46,820
‫Now we could also have used the snear here,

485
00:28:46,820 --> 00:28:48,373
‫let's take a look at that.

486
00:28:49,560 --> 00:28:51,833
‫And so that would of looked a bit different.

487
00:28:51,833 --> 00:28:54,830
‫So in this case, we would of defined the point

488
00:28:54,830 --> 00:28:57,600
‫using the longitude and the latitude that we got,

489
00:28:57,600 --> 00:28:59,498
‫and then we would of specified the maximum distance

490
00:28:59,498 --> 00:29:01,223
‫here in meters.

491
00:29:01,223 --> 00:29:03,342
‫And then in this case, we didn't need to do the conversion

492
00:29:03,342 --> 00:29:06,164
‫to radians.

493
00:29:06,164 --> 00:29:07,890
‫Okay, what's also nice about this one

494
00:29:07,890 --> 00:29:10,188
‫is that we can specify a minimum distance.

495
00:29:10,188 --> 00:29:12,782
‫And so with this, we could for example exclude

496
00:29:12,782 --> 00:29:16,779
‫tours that are only 50 miles away from our starting point,

497
00:29:16,779 --> 00:29:18,040
‫okay?

498
00:29:18,040 --> 00:29:20,270
‫So if you someday need something like this,

499
00:29:20,270 --> 00:29:23,993
‫then you can always use the new operator here as well.

500
00:29:25,071 --> 00:29:26,503
‫Okay, great.

501
00:29:27,916 --> 00:29:30,468
‫So with this geospatial query that we just defined here,

502
00:29:30,468 --> 00:29:33,600
‫we basically found documents that are located

503
00:29:33,600 --> 00:29:36,401
‫within a certain distance of our starting point.

504
00:29:36,401 --> 00:29:39,500
‫But what if we actually wanted to know the exact

505
00:29:39,500 --> 00:29:43,600
‫distances of all the tours to that starting point?

506
00:29:43,600 --> 00:29:46,300
‫Well that's exactly what we're going to calculate

507
00:29:46,300 --> 00:29:47,683
‫in the next lecture.

