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.