Query Firestore based on realtime geolocation data using RxJS. https://github.com/codediodeio/geofirex

- PRO https://angularfirebase.com/pro
- CyferLinx https://www.cyferlinx.com/
- PodMap https://podmap.org/
- AGM https://angular-maps.com/
- Firestore https://firebase.google.com/docs/firestore/
- GeoHash Viewer https://www.movable-type.co.uk/scripts/geohash.html
2024-02-04T07:27:24.060Z
nova-2
2-general-nova
2024-01-09.29447
30089e05-99d1-4376-b32e-c263170674af
66e22876-c075-4b6e-9bdd-5f62fafae8e7
37ebd48540e4a3fa8469958bae8bdfe1b41d305276793edfb98b48184baed3a7
67875a7f-c9c4-48a0-aa55-5bdb8a91c34a
deprecated
Real time geolocation is behind some of the most awesome apps in the world such as Uber, Instagram, and Waze to name a few, but building these features from scratch a lot of complex math and advanced data modeling.
But fortunately, there's tools we can use to build features like this without any trigonometry and we do it in the next few minutes.
If you're new here, like and subscribe.
And if you're serious about building apps like this, consider becoming a pro member at AngularFire base.com.
Our goal today is to use Firestore and Angular Google Maps to build a real time geolocation feature.
So we'll be able to say, give us all documents that are within x kilometers of some center point and have that query update in real time.
But before we get going, I have a couple examples of real world Angular Firebase apps that use geolocation features.
The first one is CypherLinks, which was built by an Angular Firebase Pro member and is essentially a LinkedIn for coders that allows you to find programmers geographically based on a filtered set of criteria.
And the next one is podmap.org, which is an open source project using Angular and Firebase that allows you to locate podcasts from around the world.
Check out those links in the description, but the next thing I wanna talk about is how geo queries actually work because they're a lot different than a normal query that you would make in Firestore.
So we create this fractal pattern where we have a grid of numbers and letters that segment the globe, Then we can build out a string value by repeating this pattern over and over again inside of each cell.
So every additional character in the string will be an additional level of precision for the location.
We're gonna be saving our geohashes as 9 characters, which is precise to about 4 and a half meters squared.
If you go to movabletypes.org, you can explore the bounding boxes for different geohashes.
If we want to query Firestore for all of the documents Inside of a single geohash, it's actually pretty straightforward.
We can set the starting point as the geohash, the endpoint as the hash plus a high Unicode character, Then we can order by the property that has that hash and then do start at, end at.
But here's the problem.
Let's imagine Kathy and Tim are next door neighbors And Tim does a search within this geohash.
Even though Cathy is right next door, he's only going to get results inside of his geohash.
So to get the true results, you would have to get all of the neighboring GeoHashes as well and then draw a radius around them to find anything within that radius.
And there's a bunch of other little edge cases that you'll run into as well, which is why I decided to just create a library that handles all this stuff under the hood.
It's called GeoFireX, and it uses RxJS and Firestore to make these queries possible.
But don't worry, I didn't do any of the trigonometry myself.
I left all that to an awesome library called Turf JS.
And it's compatible with both Flat Earth and Round Earth theories.
It's also compatible with any JavaScript framework long as it's using Firebase and RxJS.
Let's go ahead and get started from a brand new Angular app.
And then the first thing we'll do is install the Angular Google Maps package, which is a great component library if using Google Maps.
From your Firebase project, you can go to the Google Cloud Platform console and enable the Google Maps JavaScript API.
From there, we can install Angular Google Maps in our app as well as Firebase and GeoFire X.
Now at this point, if you're using Angular or Ionic, I would recommend using the AngularFire 2 library.
But the bare minimum thing you need to do is just initialize a Firebase app.
So that should look something like this code here.
Then you'll also want to initialize Angular Google Maps with your API key which you can do here in the app module.
Now let's create a basic map with AGM which is super easy.
The first thing we wanna do is go into our CSS and make sure we give it a width and height of something other than 0.
Otherwise, you won't be able to see the map at all.
After that, we can just declare an AGM map component and give it a starting latitude and longitude point.
We can also drop in a marker and give it a latitude and longitude as well, And that will just pop up on the map at that point.
What we'll do next is loop over a collection of documents in Firestore and render them on the map as these markers.
One of the special things that GeoFireX does is that it saves data in a format that can be queried.
In order to make Geo queries, you need to have an object on the document That contains a geohash and a geopoint.
The library will format this for you automatically, but you can save multiple geopoints on a single document, so you can do Geo Queries against multiple parameters.
So let's go ahead and make a query against this existing dataset.
I'm gonna go ahead and import GeoFireX as well as our Firebase app.
Then we can initialize GeoFireX by passing it a reference to our Firebase app.
And then we'll also declare a property called points, which is an observable of the actual documents that we query.
There are several variables that are needed to make a geo query.
The first one is your center point, which can just be a latitude and longitude.
You can create a geo hash with the library by calling the point method.
It can do a bunch of other things like return geo JSON and calculate distance and bearing and things like that.
Then the next variable that you'll need is the radius that you'll draw around the center point, which will always be in kilometers.
Under the hood, the library uses turfjs to calculate the Haversine distance which also takes into account the curvature of the Earth.
And lastly, we need to specify the object that contains the geo data because remember, a single document can have multiple geo points that can be queried against.
Then the next thing we do is make a reference to the Firestore collection.
This is just a wrapper for the main SDK that provides some additional functionality for geolocation.
To perform a geo query, you can use the within method that will take in the center radius and field.
And that returns an observable that you can just subscribe to, and it will stay in sync with any changes that happen in real time to that collection.
But because we're using RxJS, we can do this in a little bit more of a dynamic way.
For example, let's say, the user clicks a button that will expand the radius to a different value.
For that, we could set up the radius as a behavior subject which itself is an observable that can have new values pushed to it.
Then we'll define our observable points as the radius behavior subject that has been switch mapped to the actual observable geo query.
And I would like point out that within returns a hot observable that is cached to the last value.
That means you can have multiple subscribers to it and you will only be charged for the initial document read.
So by setting this up with Switch Map, we can now change the radius and get a whole new query each time the user clicks a button.
For example, we just need to call radius next And everything else will change reactively.
Now we need to unwrap the observable of our locations.
In Angular, we can do this very conveniently with the async pipe, but in other frameworks, you'd want to call subscribe on the observable and handle it accordingly.
Inside of our AGM Marker will do an n g four loop and will loop over each point of points using the async pipe to unwrap it because it returns an observable array of document data.
This gives us access to all of the data on each document, But it also returns some additional metadata that's specifically designed for building real time map features.
For example, it returns the distance and bearing that this document was found at Relative to the query center point, which can only be figured out at runtime, you might query a collection of restaurants that are relative to a user's current GPS position on their phone, And the query metadata gives you the information needed to show the distance to that point to the user in the UI.
And that will be by default on the query metadata on the return points.
I have a premade demo that I'd use for integration testing and every point in the document is a specific distance and bearing from the center.
And the actual gray circle is the radius of the query.
And if we click on any of these points, we'll also see that query metadata which again is the distance and bearing.
What's really cool about Firestore is everything is just real time by default.
So imagine we have one of these documents that are being written to every seconds as the user's position moves, it will update in the UI like we see happening here with the blue marker.
But as soon as it falls out of range, it disappears from the query and also the Why?
There's a bunch of other little features that I've added to GeoVirX specifically for working with tools like Mapbox and Google Maps.
If you find it useful, make sure to star it And please report any issues that you encounter when using it.
I'm gonna go ahead and wrap things up there.
Thanks so much for watching, and I'll talk to you soon.

Speaker 0: Real time geolocation is behind some of the most awesome apps in the world such as Uber, Instagram, and Waze to name a few, but building these features from scratch a lot of complex math and advanced data modeling. But fortunately, there's tools we can use to build features like this without any trigonometry and we do it in the next few minutes. If you're new here, like and subscribe. And if you're serious about building apps like this, consider becoming a pro member at AngularFire base.com. Our goal today is to use Firestore and Angular Google Maps to build a real time geolocation feature.

So we'll be able to say, give us all documents that are within x kilometers of some center point and have that query update in real time. But before we get going, I have a couple examples of real world Angular Firebase apps that use geolocation features. The first one is CypherLinks, which was built by an Angular Firebase Pro member and is essentially a LinkedIn for coders that allows you to find programmers geographically based on a filtered set of criteria. And the next one is podmap.org, which is an open source project using Angular and Firebase that allows you to locate podcasts from around the world. Check out those links in the description, but the next thing I wanna talk about is how geo queries actually work because they're a lot different than a normal query that you would make in Firestore.

So we create this fractal pattern where we have a grid of numbers and letters that segment the globe, Then we can build out a string value by repeating this pattern over and over again inside of each cell. So every additional character in the string will be an additional level of precision for the location. We're gonna be saving our geohashes as 9 characters, which is precise to about 4 and a half meters squared. If you go to movabletypes.org, you can explore the bounding boxes for different geohashes. If we want to query Firestore for all of the documents Inside of a single geohash, it's actually pretty straightforward.

We can set the starting point as the geohash, the endpoint as the hash plus a high Unicode character, Then we can order by the property that has that hash and then do start at, end at. But here's the problem. Let's imagine Kathy and Tim are next door neighbors And Tim does a search within this geohash. Even though Cathy is right next door, he's only going to get results inside of his geohash. So to get the true results, you would have to get all of the neighboring GeoHashes as well and then draw a radius around them to find anything within that radius.

And there's a bunch of other little edge cases that you'll run into as well, which is why I decided to just create a library that handles all this stuff under the hood. It's called GeoFireX, and it uses RxJS and Firestore to make these queries possible. But don't worry, I didn't do any of the trigonometry myself. I left all that to an awesome library called Turf JS. And it's compatible with both Flat Earth and Round Earth theories.

It's also compatible with any JavaScript framework long as it's using Firebase and RxJS. Let's go ahead and get started from a brand new Angular app. And then the first thing we'll do is install the Angular Google Maps package, which is a great component library if using Google Maps. From your Firebase project, you can go to the Google Cloud Platform console and enable the Google Maps JavaScript API. From there, we can install Angular Google Maps in our app as well as Firebase and GeoFire X.

Now at this point, if you're using Angular or Ionic, I would recommend using the AngularFire 2 library. But the bare minimum thing you need to do is just initialize a Firebase app. So that should look something like this code here. Then you'll also want to initialize Angular Google Maps with your API key which you can do here in the app module. Now let's create a basic map with AGM which is super easy.

The first thing we wanna do is go into our CSS and make sure we give it a width and height of something other than 0. Otherwise, you won't be able to see the map at all. After that, we can just declare an AGM map component and give it a starting latitude and longitude point. We can also drop in a marker and give it a latitude and longitude as well, And that will just pop up on the map at that point. What we'll do next is loop over a collection of documents in Firestore and render them on the map as these markers.

One of the special things that GeoFireX does is that it saves data in a format that can be queried. In order to make Geo queries, you need to have an object on the document That contains a geohash and a geopoint. The library will format this for you automatically, but you can save multiple geopoints on a single document, so you can do Geo Queries against multiple parameters. So let's go ahead and make a query against this existing dataset. I'm gonna go ahead and import GeoFireX as well as our Firebase app.

Then we can initialize GeoFireX by passing it a reference to our Firebase app. And then we'll also declare a property called points, which is an observable of the actual documents that we query. There are several variables that are needed to make a geo query. The first one is your center point, which can just be a latitude and longitude. You can create a geo hash with the library by calling the point method.

It can do a bunch of other things like return geo JSON and calculate distance and bearing and things like that. Then the next variable that you'll need is the radius that you'll draw around the center point, which will always be in kilometers. Under the hood, the library uses turfjs to calculate the Haversine distance which also takes into account the curvature of the Earth. And lastly, we need to specify the object that contains the geo data because remember, a single document can have multiple geo points that can be queried against. Then the next thing we do is make a reference to the Firestore collection.

This is just a wrapper for the main SDK that provides some additional functionality for geolocation. To perform a geo query, you can use the within method that will take in the center radius and field. And that returns an observable that you can just subscribe to, and it will stay in sync with any changes that happen in real time to that collection. But because we're using RxJS, we can do this in a little bit more of a dynamic way. For example, let's say, the user clicks a button that will expand the radius to a different value.

For that, we could set up the radius as a behavior subject which itself is an observable that can have new values pushed to it. Then we'll define our observable points as the radius behavior subject that has been switch mapped to the actual observable geo query. And I would like point out that within returns a hot observable that is cached to the last value. That means you can have multiple subscribers to it and you will only be charged for the initial document read. So by setting this up with Switch Map, we can now change the radius and get a whole new query each time the user clicks a button.

For example, we just need to call radius next And everything else will change reactively. Now we need to unwrap the observable of our locations. In Angular, we can do this very conveniently with the async pipe, but in other frameworks, you'd want to call subscribe on the observable and handle it accordingly. Inside of our AGM Marker will do an n g four loop and will loop over each point of points using the async pipe to unwrap it because it returns an observable array of document data. This gives us access to all of the data on each document, But it also returns some additional metadata that's specifically designed for building real time map features.

For example, it returns the distance and bearing that this document was found at Relative to the query center point, which can only be figured out at runtime, you might query a collection of restaurants that are relative to a user's current GPS position on their phone, And the query metadata gives you the information needed to show the distance to that point to the user in the UI. And that will be by default on the query metadata on the return points. I have a premade demo that I'd use for integration testing and every point in the document is a specific distance and bearing from the center. And the actual gray circle is the radius of the query. And if we click on any of these points, we'll also see that query metadata which again is the distance and bearing.

What's really cool about Firestore is everything is just real time by default. So imagine we have one of these documents that are being written to every seconds as the user's position moves, it will update in the UI like we see happening here with the blue marker. But as soon as it falls out of range, it disappears from the query and also the Why? There's a bunch of other little features that I've added to GeoVirX specifically for working with tools like Mapbox and Google Maps. If you find it useful, make sure to star it And please report any issues that you encounter when using it.

I'm gonna go ahead and wrap things up there. Thanks so much for watching, and I'll talk to you soon.
Real time geolocation is behind some of the most awesome apps in the world such as Uber, Instagram, and Waze to name a few, but building these features from scratch a lot of complex math and advanced data modeling. But fortunately, there's tools we can use to build features like this without any trigonometry and we do it in the next few minutes.
space exploration
geography
geometry
technology
If you're new here, like and subscribe. And if you're serious about building apps like this, consider becoming a pro member at AngularFire base.com. Our goal today is to use Firestore and Angular Google Maps to build a real time geolocation feature. So we'll be able to say, give us all documents that are within x kilometers of some center point and have that query update in real time. But before we get going, I have a couple examples of real world Angular Firebase apps that use geolocation features. The first one is CypherLinks, which was built by an Angular Firebase Pro member and is essentially a LinkedIn for coders that allows you to find programmers geographically based on a filtered set of criteria.
And the next one is podmap.org, which is an open source project using Angular and Firebase that allows you to locate podcasts from around the world. Check out those links in the description, but the next thing I wanna talk about is how geo queries actually work because they're a lot different than a normal query that you would make in Firestore.
podcasts
So we create this fractal pattern where we have a grid of numbers and letters that segment the globe, Then we can build out a string value by repeating this pattern over and over again inside of each cell. So every additional character in the string will be an additional level of precision for the location.
mathematics
We're gonna be saving our geohashes as 9 characters, which is precise to about 4 and a half meters squared. If you go to movabletypes.org, you can explore the bounding boxes for different geohashes. If we want to query Firestore for all of the documents Inside of a single geohash, it's actually pretty straightforward. We can set the starting point as the geohash, the endpoint as the hash plus a high Unicode character, Then we can order by the property that has that hash and then do start at, end at. But here's the problem. Let's imagine Kathy and Tim are next door neighbors And Tim does a search within this geohash. Even though Cathy is right next door, he's only going to get results inside of his geohash. So to get the true results, you would have to get all of the neighboring GeoHashes as well and then draw a radius around them to find anything within that radius. And there's a bunch of other little edge cases that you'll run into as well, which is why I decided to just create a library that handles all this stuff under the hood. It's called GeoFireX, and it uses RxJS and Firestore to make these queries possible. But don't worry, I didn't do any of the trigonometry myself. I left all that to an awesome library called Turf JS. And it's compatible with both Flat Earth and Round Earth theories. It's also compatible with any JavaScript framework long as it's using Firebase and RxJS. Let's go ahead and get started from a brand new Angular app. And then the first thing we'll do is install the Angular Google Maps package, which is a great component library if using Google Maps. From your Firebase project, you can go to the Google Cloud Platform console and enable the Google Maps JavaScript API. From there, we can install Angular Google Maps in our app as well as Firebase and GeoFire X. Now at this point, if you're using Angular or Ionic, I would recommend using the AngularFire 2 library. But the bare minimum thing you need to do is just initialize a Firebase app. So that should look something like this code here. Then you'll also want to initialize Angular Google Maps with your API key which you can do here in the app module. Now let's create a basic map with AGM which is super easy. The first thing we wanna do is go into our CSS and make sure we give it a width and height of something other than 0. Otherwise, you won't be able to see the map at all. After that, we can just declare an AGM map component and give it a starting latitude and longitude point. We can also drop in a marker and give it a latitude and longitude as well, And that will just pop up on the map at that point. What we'll do next is loop over a collection of documents in Firestore and render them on the map as these markers. One of the special things that GeoFireX does is that it saves data in a format that can be queried. In order to make Geo queries, you need to have an object on the document That contains a geohash and a geopoint. The library will format this for you automatically, but you can save multiple geopoints on a single document, so you can do Geo Queries against multiple parameters. So let's go ahead and make a query against this existing dataset. I'm gonna go ahead and import GeoFireX as well as our Firebase app. Then we can initialize GeoFireX by passing it a reference to our Firebase app. And then we'll also declare a property called points, which is an observable of the actual documents that we query.
There are several variables that are needed to make a geo query. The first one is your center point, which can just be a latitude and longitude. You can create a geo hash with the library by calling the point method. It can do a bunch of other things like return geo JSON and calculate distance and bearing and things like that. Then the next variable that you'll need is the radius that you'll draw around the center point, which will always be in kilometers. Under the hood, the library uses turfjs to calculate the Haversine distance which also takes into account the curvature of the Earth. And lastly, we need to specify the object that contains the geo data because remember, a single document can have multiple geo points that can be queried against.
geography
geometry
Then the next thing we do is make a reference to the Firestore collection. This is just a wrapper for the main SDK that provides some additional functionality for geolocation. To perform a geo query, you can use the within method that will take in the center radius and field. And that returns an observable that you can just subscribe to, and it will stay in sync with any changes that happen in real time to that collection. But because we're using RxJS, we can do this in a little bit more of a dynamic way. For example, let's say, the user clicks a button that will expand the radius to a different value.
For that, we could set up the radius as a behavior subject which itself is an observable that can have new values pushed to it. Then we'll define our observable points as the radius behavior subject that has been switch mapped to the actual observable geo query. And I would like point out that within returns a hot observable that is cached to the last value. That means you can have multiple subscribers to it and you will only be charged for the initial document read.
geometry
data
So by setting this up with Switch Map, we can now change the radius and get a whole new query each time the user clicks a button. For example, we just need to call radius next And everything else will change reactively. Now we need to unwrap the observable of our locations. In Angular, we can do this very conveniently with the async pipe, but in other frameworks, you'd want to call subscribe on the observable and handle it accordingly. Inside of our AGM Marker will do an n g four loop and will loop over each point of points using the async pipe to unwrap it because it returns an observable array of document data.
This gives us access to all of the data on each document, But it also returns some additional metadata that's specifically designed for building real time map features. For example, it returns the distance and bearing that this document was found at Relative to the query center point, which can only be figured out at runtime, you might query a collection of restaurants that are relative to a user's current GPS position on their phone, And the query metadata gives you the information needed to show the distance to that point to the user in the UI.
databases
data
data management
And that will be by default on the query metadata on the return points. I have a premade demo that I'd use for integration testing and every point in the document is a specific distance and bearing from the center. And the actual gray circle is the radius of the query. And if we click on any of these points, we'll also see that query metadata which again is the distance and bearing. What's really cool about Firestore is everything is just real time by default. So imagine we have one of these documents that are being written to every seconds as the user's position moves, it will update in the UI like we see happening here with the blue marker. But as soon as it falls out of range, it disappears from the query and also the Why? There's a bunch of other little features that I've added to GeoVirX specifically for working with tools like Mapbox and Google Maps. If you find it useful, make sure to star it And please report any issues that you encounter when using it. I'm gonna go ahead and wrap things up there. Thanks so much for watching, and I'll talk to you soon.
Real time geolocation is behind some of the most awesome apps in the world such as Uber, Instagram, and Waze to name a few, but building these features from scratch a lot of complex math and advanced data modeling. But fortunately, there's tools we can use to build features like this without any trigonometry and we do it in the next few minutes. If you're new here, like and subscribe. And if you're serious about building apps like this, consider becoming a pro member at AngularFire base.com. Our goal today is to use Firestore and Angular Google Maps to build a real time geolocation feature. So we'll be able to say, give us all documents that are within x kilometers of some center point and have that query update in real time. But before we get going, I have a couple examples of real world Angular Firebase apps that use geolocation features. The first one is CypherLinks, which was built by an Angular Firebase Pro member and is essentially a LinkedIn for coders that allows you to find programmers geographically based on a filtered set of criteria. And the next one is podmap.org, which is an open source project using Angular and Firebase that allows you to locate podcasts from around the world. Check out those links in the description, but the next thing I wanna talk about is how geo queries actually work because they're a lot different than a normal query that you would make in Firestore. So we create this fractal pattern where we have a grid of numbers and letters that segment the globe, Then we can build out a string value by repeating this pattern over and over again inside of each cell. So every additional character in the string will be an additional level of precision for the location. We're gonna be saving our geohashes as 9 characters, which is precise to about 4 and a half meters squared. If you go to movabletypes.org, you can explore the bounding boxes for different geohashes. If we want to query Firestore for all of the documents Inside of a single geohash, it's actually pretty straightforward. We can set the starting point as the geohash, the endpoint as the hash plus a high Unicode character, Then we can order by the property that has that hash and then do start at, end at. But here's the problem. Let's imagine Kathy and Tim are next door neighbors And Tim does a search within this geohash. Even though Cathy is right next door, he's only going to get results inside of his geohash. So to get the true results, you would have to get all of the neighboring GeoHashes as well and then draw a radius around them to find anything within that radius. And there's a bunch of other little edge cases that you'll run into as well, which is why I decided to just create a library that handles all this stuff under the hood. It's called GeoFireX, and it uses RxJS and Firestore to make these queries possible. But don't worry, I didn't do any of the trigonometry myself. I left all that to an awesome library called Turf JS. And it's compatible with both Flat Earth and Round Earth theories. It's also compatible with any JavaScript framework long as it's using Firebase and RxJS. Let's go ahead and get started from a brand new Angular app. And then the first thing we'll do is install the Angular Google Maps package, which is a great component library if using Google Maps. From your Firebase project, you can go to the Google Cloud Platform console and enable the Google Maps JavaScript API. From there, we can install Angular Google Maps in our app as well as Firebase and GeoFire X. Now at this point, if you're using Angular or Ionic, I would recommend using the AngularFire 2 library. But the bare minimum thing you need to do is just initialize a Firebase app. So that should look something like this code here. Then you'll also want to initialize Angular Google Maps with your API key which you can do here in the app module. Now let's create a basic map with AGM which is super easy. The first thing we wanna do is go into our CSS and make sure we give it a width and height of something other than 0. Otherwise, you won't be able to see the map at all. After that, we can just declare an AGM map component and give it a starting latitude and longitude point. We can also drop in a marker and give it a latitude and longitude as well, And that will just pop up on the map at that point. What we'll do next is loop over a collection of documents in Firestore and render them on the map as these markers. One of the special things that GeoFireX does is that it saves data in a format that can be queried. In order to make Geo queries, you need to have an object on the document That contains a geohash and a geopoint. The library will format this for you automatically, but you can save multiple geopoints on a single document, so you can do Geo Queries against multiple parameters. So let's go ahead and make a query against this existing dataset. I'm gonna go ahead and import GeoFireX as well as our Firebase app. Then we can initialize GeoFireX by passing it a reference to our Firebase app. And then we'll also declare a property called points, which is an observable of the actual documents that we query. There are several variables that are needed to make a geo query. The first one is your center point, which can just be a latitude and longitude. You can create a geo hash with the library by calling the point method. It can do a bunch of other things like return geo JSON and calculate distance and bearing and things like that. Then the next variable that you'll need is the radius that you'll draw around the center point, which will always be in kilometers. Under the hood, the library uses turfjs to calculate the Haversine distance which also takes into account the curvature of the Earth. And lastly, we need to specify the object that contains the geo data because remember, a single document can have multiple geo points that can be queried against. Then the next thing we do is make a reference to the Firestore collection. This is just a wrapper for the main SDK that provides some additional functionality for geolocation. To perform a geo query, you can use the within method that will take in the center radius and field. And that returns an observable that you can just subscribe to, and it will stay in sync with any changes that happen in real time to that collection. But because we're using RxJS, we can do this in a little bit more of a dynamic way. For example, let's say, the user clicks a button that will expand the radius to a different value. For that, we could set up the radius as a behavior subject which itself is an observable that can have new values pushed to it. Then we'll define our observable points as the radius behavior subject that has been switch mapped to the actual observable geo query. And I would like point out that within returns a hot observable that is cached to the last value. That means you can have multiple subscribers to it and you will only be charged for the initial document read. So by setting this up with Switch Map, we can now change the radius and get a whole new query each time the user clicks a button. For example, we just need to call radius next And everything else will change reactively. Now we need to unwrap the observable of our locations. In Angular, we can do this very conveniently with the async pipe, but in other frameworks, you'd want to call subscribe on the observable and handle it accordingly. Inside of our AGM Marker will do an n g four loop and will loop over each point of points using the async pipe to unwrap it because it returns an observable array of document data. This gives us access to all of the data on each document, But it also returns some additional metadata that's specifically designed for building real time map features. For example, it returns the distance and bearing that this document was found at Relative to the query center point, which can only be figured out at runtime, you might query a collection of restaurants that are relative to a user's current GPS position on their phone, And the query metadata gives you the information needed to show the distance to that point to the user in the UI. And that will be by default on the query metadata on the return points. I have a premade demo that I'd use for integration testing and every point in the document is a specific distance and bearing from the center. And the actual gray circle is the radius of the query. And if we click on any of these points, we'll also see that query metadata which again is the distance and bearing. What's really cool about Firestore is everything is just real time by default. So imagine we have one of these documents that are being written to every seconds as the user's position moves, it will update in the UI like we see happening here with the blue marker. But as soon as it falls out of range, it disappears from the query and also the Why? There's a bunch of other little features that I've added to GeoVirX specifically for working with tools like Mapbox and Google Maps. If you find it useful, make sure to star it And please report any issues that you encounter when using it. I'm gonna go ahead and wrap things up there. Thanks so much for watching, and I'll talk to you soon.
Real
real
time
time
geolocation
geolocation
is
is
behind
behind
some
some
of
of
the
the
most
most
awesome
awesome
apps
apps
in
in
the
the
world
world
such
such
as
as
Uber,
uber
Instagram,
instagram
and
and
Waze
waze
to
to
name
name
a
a
few,
few
but
but
building
building
these
these
features
features
from
from
scratch
scratch
a
a
lot
lot
of
of
complex
complex
math
math
and
and
advanced
advanced
data
data
modeling.
modeling
But
but
fortunately,
fortunately
there's
there's
tools
tools
we
we
can
can
use
use
to
to
build
build
features
features
like
like
this
this
without
without
any
any
trigonometry
trigonometry
and
and
we
we
do
do
it
it
in
in
the
the
next
next
few
few
minutes.
minutes
If
if
you're
you're
new
new
here,
here
like
like
and
and
subscribe.
subscribe
And
and
if
if
you're
you're
serious
serious
about
about
building
building
apps
apps
like
like
this,
this
consider
consider
becoming
becoming
a
a
pro
pro
member
member
at
at
AngularFire
angularfire
base.com.
base.com
Our
our
goal
goal
today
today
is
is
to
to
use
use
Firestore
firestore
and
and
Angular
angular
Google
google
Maps
maps
to
to
build
build
a
a
real
real
time
time
geolocation
geolocation
feature.
feature
So
so
we'll
we'll
be
be
able
able
to
to
say,
say
give
give
us
us
all
all
documents
documents
that
that
are
are
within
within
x
x
kilometers
kilometers
of
of
some
some
center
center
point
point
and
and
have
have
that
that
query
query
update
update
in
in
real
real
time.
time
But
but
before
before
we
we
get
get
going,
going
I
i
have
have
a
a
couple
couple
examples
examples
of
of
real
real
world
world
Angular
angular
Firebase
firebase
apps
apps
that
that
use
use
geolocation
geolocation
features.
features
The
the
first
first
one
one
is
is
CypherLinks,
cypherlinks
which
which
was
was
built
built
by
by
an
an
Angular
angular
Firebase
firebase
Pro
pro
member
member
and
and
is
is
essentially
essentially
a
a
LinkedIn
linkedin
for
for
coders
coders
that
that
allows
allows
you
you
to
to
find
find
programmers
programmers
geographically
geographically
based
based
on
on
a
a
filtered
filtered
set
set
of
of
criteria.
criteria
And
and
the
the
next
next
one
one
is
is
podmap.org,
podmap.org
which
which
is
is
an
an
open
open
source
source
project
project
using
using
Angular
angular
and
and
Firebase
firebase
that
that
allows
allows
you
you
to
to
locate
locate
podcasts
podcasts
from
from
around
around
the
the
world.
world
Check
check
out
out
those
those
links
links
in
in
the
the
description,
description
but
but
the
the
next
next
thing
thing
I
i
wanna
wanna
talk
talk
about
about
is
is
how
how
geo
geo
queries
queries
actually
actually
work
work
because
because
they're
they're
a
a
lot
lot
different
different
than
than
a
a
normal
normal
query
query
that
that
you
you
would
would
make
make
in
in
Firestore.
firestore
So
so
we
we
create
create
this
this
fractal
fractal
pattern
pattern
where
where
we
we
have
have
a
a
grid
grid
of
of
numbers
numbers
and
and
letters
letters
that
that
segment
segment
the
the
globe,
globe
Then
then
we
we
can
can
build
build
out
out
a
a
string
string
value
value
by
by
repeating
repeating
this
this
pattern
pattern
over
over
and
and
over
over
again
again
inside
inside
of
of
each
each
cell.
cell
So
so
every
every
additional
additional
character
character
in
in
the
the
string
string
will
will
be
be
an
an
additional
additional
level
level
of
of
precision
precision
for
for
the
the
location.
location
We're
we're
gonna
gonna
be
be
saving
saving
our
our
geohashes
geohashes
as
as
9
9
characters,
characters
which
which
is
is
precise
precise
to
to
about
about
4
4
and
and
a
a
half
half
meters
meters
squared.
squared
If
if
you
you
go
go
to
to
movabletypes.org,
movabletypes.org
you
you
can
can
explore
explore
the
the
bounding
bounding
boxes
boxes
for
for
different
different
geohashes.
geohashes
If
if
we
we
want
want
to
to
query
query
Firestore
firestore
for
for
all
all
of
of
the
the
documents
documents
Inside
inside
of
of
a
a
single
single
geohash,
geohash
it's
it's
actually
actually
pretty
pretty
straightforward.
straightforward
We
we
can
can
set
set
the
the
starting
starting
point
point
as
as
the
the
geohash,
geohash
the
the
endpoint
endpoint
as
as
the
the
hash
hash
plus
plus
a
a
high
high
Unicode
unicode
character,
character
Then
then
we
we
can
can
order
order
by
by
the
the
property
property
that
that
has
has
that
that
hash
hash
and
and
then
then
do
do
start
start
at,
at
end
end
at.
at
But
but
here's
here's
the
the
problem.
problem
Let's
let's
imagine
imagine
Kathy
kathy
and
and
Tim
tim
are
are
next
next
door
door
neighbors
neighbors
And
and
Tim
tim
does
does
a
a
search
search
within
within
this
this
geohash.
geohash
Even
even
though
though
Cathy
cathy
is
is
right
right
next
next
door,
door
he's
he's
only
only
going
going
to
to
get
get
results
results
inside
inside
of
of
his
his
geohash.
geohash
So
so
to
to
get
get
the
the
true
true
results,
results
you
you
would
would
have
have
to
to
get
get
all
all
of
of
the
the
neighboring
neighboring
GeoHashes
geohashes
as
as
well
well
and
and
then
then
draw
draw
a
a
radius
radius
around
around
them
them
to
to
find
find
anything
anything
within
within
that
that
radius.
radius
And
and
there's
there's
a
a
bunch
bunch
of
of
other
other
little
little
edge
edge
cases
cases
that
that
you'll
you'll
run
run
into
into
as
as
well,
well
which
which
is
is
why
why
I
i
decided
decided
to
to
just
just
create
create
a
a
library
library
that
that
handles
handles
all
all
this
this
stuff
stuff
under
under
the
the
hood.
hood
It's
it's
called
called
GeoFireX,
geofirex
and
and
it
it
uses
uses
RxJS
rxjs
and
and
Firestore
firestore
to
to
make
make
these
these
queries
queries
possible.
possible
But
but
don't
don't
worry,
worry
I
i
didn't
didn't
do
do
any
any
of
of
the
the
trigonometry
trigonometry
myself.
myself
I
i
left
left
all
all
that
that
to
to
an
an
awesome
awesome
library
library
called
called
Turf
turf
JS.
js
And
and
it's
it's
compatible
compatible
with
with
both
both
Flat
flat
Earth
earth
and
and
Round
round
Earth
earth
theories.
theories
It's
it's
also
also
compatible
compatible
with
with
any
any
JavaScript
javascript
framework
framework
long
long
as
as
it's
it's
using
using
Firebase
firebase
and
and
RxJS.
rxjs
Let's
let's
go
go
ahead
ahead
and
and
get
get
started
started
from
from
a
a
brand
brand
new
new
Angular
angular
app.
app
And
and
then
then
the
the
first
first
thing
thing
we'll
we'll
do
do
is
is
install
install
the
the
Angular
angular
Google
google
Maps
maps
package,
package
which
which
is
is
a
a
great
great
component
component
library
library
if
if
using
using
Google
google
Maps.
maps
From
from
your
your
Firebase
firebase
project,
project
you
you
can
can
go
go
to
to
the
the
Google
google
Cloud
cloud
Platform
platform
console
console
and
and
enable
enable
the
the
Google
google
Maps
maps
JavaScript
javascript
API.
api
From
from
there,
there
we
we
can
can
install
install
Angular
angular
Google
google
Maps
maps
in
in
our
our
app
app
as
as
well
well
as
as
Firebase
firebase
and
and
GeoFire
geofire
X.
x
Now
now
at
at
this
this
point,
point
if
if
you're
you're
using
using
Angular
angular
or
or
Ionic,
ionic
I
i
would
would
recommend
recommend
using
using
the
the
AngularFire
angularfire
2
2
library.
library
But
but
the
the
bare
bare
minimum
minimum
thing
thing
you
you
need
need
to
to
do
do
is
is
just
just
initialize
initialize
a
a
Firebase
firebase
app.
app
So
so
that
that
should
should
look
look
something
something
like
like
this
this
code
code
here.
here
Then
then
you'll
you'll
also
also
want
want
to
to
initialize
initialize
Angular
angular
Google
google
Maps
maps
with
with
your
your
API
api
key
key
which
which
you
you
can
can
do
do
here
here
in
in
the
the
app
app
module.
module
Now
now
let's
let's
create
create
a
a
basic
basic
map
map
with
with
AGM
agm
which
which
is
is
super
super
easy.
easy
The
the
first
first
thing
thing
we
we
wanna
wanna
do
do
is
is
go
go
into
into
our
our
CSS
css
and
and
make
make
sure
sure
we
we
give
give
it
it
a
a
width
width
and
and
height
height
of
of
something
something
other
other
than
than
0.
0
Otherwise,
otherwise
you
you
won't
won't
be
be
able
able
to
to
see
see
the
the
map
map
at
at
all.
all
After
after
that,
that
we
we
can
can
just
just
declare
declare
an
an
AGM
agm
map
map
component
component
and
and
give
give
it
it
a
a
starting
starting
latitude
latitude
and
and
longitude
longitude
point.
point
We
we
can
can
also
also
drop
drop
in
in
a
a
marker
marker
and
and
give
give
it
it
a
a
latitude
latitude
and
and
longitude
longitude
as
as
well,
well
And
and
that
that
will
will
just
just
pop
pop
up
up
on
on
the
the
map
map
at
at
that
that
point.
point
What
what
we'll
we'll
do
do
next
next
is
is
loop
loop
over
over
a
a
collection
collection
of
of
documents
documents
in
in
Firestore
firestore
and
and
render
render
them
them
on
on
the
the
map
map
as
as
these
these
markers.
markers
One
one
of
of
the
the
special
special
things
things
that
that
GeoFireX
geofirex
does
does
is
is
that
that
it
it
saves
saves
data
data
in
in
a
a
format
format
that
that
can
can
be
be
queried.
queried
In
in
order
order
to
to
make
make
Geo
geo
queries,
queries
you
you
need
need
to
to
have
have
an
an
object
object
on
on
the
the
document
document
That
that
contains
contains
a
a
geohash
geohash
and
and
a
a
geopoint.
geopoint
The
the
library
library
will
will
format
format
this
this
for
for
you
you
automatically,
automatically
but
but
you
you
can
can
save
save
multiple
multiple
geopoints
geopoints
on
on
a
a
single
single
document,
document
so
so
you
you
can
can
do
do
Geo
geo
Queries
queries
against
against
multiple
multiple
parameters.
parameters
So
so
let's
let's
go
go
ahead
ahead
and
and
make
make
a
a
query
query
against
against
this
this
existing
existing
dataset.
dataset
I'm
i'm
gonna
gonna
go
go
ahead
ahead
and
and
import
import
GeoFireX
geofirex
as
as
well
well
as
as
our
our
Firebase
firebase
app.
app
Then
then
we
we
can
can
initialize
initialize
GeoFireX
geofirex
by
by
passing
passing
it
it
a
a
reference
reference
to
to
our
our
Firebase
firebase
app.
app
And
and
then
then
we'll
we'll
also
also
declare
declare
a
a
property
property
called
called
points,
points
which
which
is
is
an
an
observable
observable
of
of
the
the
actual
actual
documents
documents
that
that
we
we
query.
query
There
there
are
are
several
several
variables
variables
that
that
are
are
needed
needed
to
to
make
make
a
a
geo
geo
query.
query
The
the
first
first
one
one
is
is
your
your
center
center
point,
point
which
which
can
can
just
just
be
be
a
a
latitude
latitude
and
and
longitude.
longitude
You
you
can
can
create
create
a
a
geo
geo
hash
hash
with
with
the
the
library
library
by
by
calling
calling
the
the
point
point
method.
method
It
it
can
can
do
do
a
a
bunch
bunch
of
of
other
other
things
things
like
like
return
return
geo
geo
JSON
json
and
and
calculate
calculate
distance
distance
and
and
bearing
bearing
and
and
things
things
like
like
that.
that
Then
then
the
the
next
next
variable
variable
that
that
you'll
you'll
need
need
is
is
the
the
radius
radius
that
that
you'll
you'll
draw
draw
around
around
the
the
center
center
point,
point
which
which
will
will
always
always
be
be
in
in
kilometers.
kilometers
Under
under
the
the
hood,
hood
the
the
library
library
uses
uses
turfjs
turfjs
to
to
calculate
calculate
the
the
Haversine
haversine
distance
distance
which
which
also
also
takes
takes
into
into
account
account
the
the
curvature
curvature
of
of
the
the
Earth.
earth
And
and
lastly,
lastly
we
we
need
need
to
to
specify
specify
the
the
object
object
that
that
contains
contains
the
the
geo
geo
data
data
because
because
remember,
remember
a
a
single
single
document
document
can
can
have
have
multiple
multiple
geo
geo
points
points
that
that
can
can
be
be
queried
queried
against.
against
Then
then
the
the
next
next
thing
thing
we
we
do
do
is
is
make
make
a
a
reference
reference
to
to
the
the
Firestore
firestore
collection.
collection
This
this
is
is
just
just
a
a
wrapper
wrapper
for
for
the
the
main
main
SDK
sdk
that
that
provides
provides
some
some
additional
additional
functionality
functionality
for
for
geolocation.
geolocation
To
to
perform
perform
a
a
geo
geo
query,
query
you
you
can
can
use
use
the
the
within
within
method
method
that
that
will
will
take
take
in
in
the
the
center
center
radius
radius
and
and
field.
field
And
and
that
that
returns
returns
an
an
observable
observable
that
that
you
you
can
can
just
just
subscribe
subscribe
to,
to
and
and
it
it
will
will
stay
stay
in
in
sync
sync
with
with
any
any
changes
changes
that
that
happen
happen
in
in
real
real
time
time
to
to
that
that
collection.
collection
But
but
because
because
we're
we're
using
using
RxJS,
rxjs
we
we
can
can
do
do
this
this
in
in
a
a
little
little
bit
bit
more
more
of
of
a
a
dynamic
dynamic
way.
way
For
for
example,
example
let's
let's
say,
say
the
the
user
user
clicks
clicks
a
a
button
button
that
that
will
will
expand
expand
the
the
radius
radius
to
to
a
a
different
different
value.
value
For
for
that,
that
we
we
could
could
set
set
up
up
the
the
radius
radius
as
as
a
a
behavior
behavior
subject
subject
which
which
itself
itself
is
is
an
an
observable
observable
that
that
can
can
have
have
new
new
values
values
pushed
pushed
to
to
it.
it
Then
then
we'll
we'll
define
define
our
our
observable
observable
points
points
as
as
the
the
radius
radius
behavior
behavior
subject
subject
that
that
has
has
been
been
switch
switch
mapped
mapped
to
to
the
the
actual
actual
observable
observable
geo
geo
query.
query
And
and
I
i
would
would
like
like
point
point
out
out
that
that
within
within
returns
returns
a
a
hot
hot
observable
observable
that
that
is
is
cached
cached
to
to
the
the
last
last
value.
value
That
that
means
means
you
you
can
can
have
have
multiple
multiple
subscribers
subscribers
to
to
it
it
and
and
you
you
will
will
only
only
be
be
charged
charged
for
for
the
the
initial
initial
document
document
read.
read
So
so
by
by
setting
setting
this
this
up
up
with
with
Switch
switch
Map,
map
we
we
can
can
now
now
change
change
the
the
radius
radius
and
and
get
get
a
a
whole
whole
new
new
query
query
each
each
time
time
the
the
user
user
clicks
clicks
a
a
button.
button
For
for
example,
example
we
we
just
just
need
need
to
to
call
call
radius
radius
next
next
And
and
everything
everything
else
else
will
will
change
change
reactively.
reactively
Now
now
we
we
need
need
to
to
unwrap
unwrap
the
the
observable
observable
of
of
our
our
locations.
locations
In
in
Angular,
angular
we
we
can
can
do
do
this
this
very
very
conveniently
conveniently
with
with
the
the
async
async
pipe,
pipe
but
but
in
in
other
other
frameworks,
frameworks
you'd
you'd
want
want
to
to
call
call
subscribe
subscribe
on
on
the
the
observable
observable
and
and
handle
handle
it
it
accordingly.
accordingly
Inside
inside
of
of
our
our
AGM
agm
Marker
marker
will
will
do
do
an
an
n
n
g
g
four
four
loop
loop
and
and
will
will
loop
loop
over
over
each
each
point
point
of
of
points
points
using
using
the
the
async
async
pipe
pipe
to
to
unwrap
unwrap
it
it
because
because
it
it
returns
returns
an
an
observable
observable
array
array
of
of
document
document
data.
data
This
this
gives
gives
us
us
access
access
to
to
all
all
of
of
the
the
data
data
on
on
each
each
document,
document
But
but
it
it
also
also
returns
returns
some
some
additional
additional
metadata
metadata
that's
that's
specifically
specifically
designed
designed
for
for
building
building
real
real
time
time
map
map
features.
features
For
for
example,
example
it
it
returns
returns
the
the
distance
distance
and
and
bearing
bearing
that
that
this
this
document
document
was
was
found
found
at
at
Relative
relative
to
to
the
the
query
query
center
center
point,
point
which
which
can
can
only
only
be
be
figured
figured
out
out
at
at
runtime,
runtime
you
you
might
might
query
query
a
a
collection
collection
of
of
restaurants
restaurants
that
that
are
are
relative
relative
to
to
a
a
user's
user's
current
current
GPS
gps
position
position
on
on
their
their
phone,
phone
And
and
the
the
query
query
metadata
metadata
gives
gives
you
you
the
the
information
information
needed
needed
to
to
show
show
the
the
distance
distance
to
to
that
that
point
point
to
to
the
the
user
user
in
in
the
the
UI.
ui
And
and
that
that
will
will
be
be
by
by
default
default
on
on
the
the
query
query
metadata
metadata
on
on
the
the
return
return
points.
points
I
i
have
have
a
a
premade
premade
demo
demo
that
that
I'd
i'd
use
use
for
for
integration
integration
testing
testing
and
and
every
every
point
point
in
in
the
the
document
document
is
is
a
a
specific
specific
distance
distance
and
and
bearing
bearing
from
from
the
the
center.
center
And
and
the
the
actual
actual
gray
gray
circle
circle
is
is
the
the
radius
radius
of
of
the
the
query.
query
And
and
if
if
we
we
click
click
on
on
any
any
of
of
these
these
points,
points
we'll
we'll
also
also
see
see
that
that
query
query
metadata
metadata
which
which
again
again
is
is
the
the
distance
distance
and
and
bearing.
bearing
What's
what's
really
really
cool
cool
about
about
Firestore
firestore
is
is
everything
everything
is
is
just
just
real
real
time
time
by
by
default.
default
So
so
imagine
imagine
we
we
have
have
one
one
of
of
these
these
documents
documents
that
that
are
are
being
being
written
written
to
to
every
every
seconds
seconds
as
as
the
the
user's
user's
position
position
moves,
moves
it
it
will
will
update
update
in
in
the
the
UI
ui
like
like
we
we
see
see
happening
happening
here
here
with
with
the
the
blue
blue
marker.
marker
But
but
as
as
soon
soon
as
as
it
it
falls
falls
out
out
of
of
range,
range
it
it
disappears
disappears
from
from
the
the
query
query
and
and
also
also
the
the
Why?
why
There's
there's
a
a
bunch
bunch
of
of
other
other
little
little
features
features
that
that
I've
i've
added
added
to
to
GeoVirX
geovirx
specifically
specifically
for
for
working
working
with
with
tools
tools
like
like
Mapbox
mapbox
and
and
Google
google
Maps.
maps
If
if
you
you
find
find
it
it
useful,
useful
make
make
sure
sure
to
to
star
star
it
it
And
and
please
please
report
report
any
any
issues
issues
that
that
you
you
encounter
encounter
when
when
using
using
it.
it
I'm
i'm
gonna
gonna
go
go
ahead
ahead
and
and
wrap
wrap
things
things
up
up
there.
there
Thanks
thanks
so
so
much
much
for
for
watching,
watching
and
and
I'll
i'll
talk
talk
to
to
you
you
soon.
soon
success
The speakers discuss various Angular navigate apps and real world projects, including C consequence and GeoFinancialX using Angular Google Maps to create a real time geolocation feature. They recommend using the Angular app and the points method to create a query against an existing dataset and explain how to use the blockchain and other functions used in the app. A demo is then introduced for integration testing and a link is provided for any issues.
Firestore Geoquery
Real time geolocation is behind some of the most awesome apps in the world such as Uber, Instagram, and Waze to name a few, but building these features from scratch a lot of complex math and advanced data modeling. But fortunately, there's tools we can use to build features like this without any trigonometry and we do it in the next few minutes. If you're new here, like and subscribe. And if you're serious about building apps like this, consider becoming a pro member at AngularFire base.com. Our goal today is to use Firestore and Angular Google Maps to build a real time geolocation feature. So we'll be able to say, give us all documents that are within x kilometers of some center point and have that query update in real time. But before we get going, I have a couple examples of real world Angular Firebase apps that use geolocation features. The first one is CypherLinks, which was built by an Angular Firebase Pro member and is essentially a LinkedIn for coders that allows you to find programmers geographically based on a filtered set of criteria. And the next one is podmap.org, which is an open source project using Angular and Firebase that allows you to locate podcasts from around the world. Check out those links in the description, but the next thing I wanna talk about is how geo queries actually work because they're a lot different than a normal query that you would make in Firestore. So we create this fractal pattern where we have a grid of numbers and letters that segment the globe, Then we can build out a string value by repeating this pattern over and over again inside of each cell. So every additional character in the string will be an additional level of precision for the location. We're gonna be saving our geohashes as 9 characters, which is precise to about 4 and a half meters squared. If you go to movabletypes.org, you can explore the bounding boxes for different geohashes. If we want to query Firestore for all of the documents Inside of a single geohash, it's actually pretty straightforward. We can set the starting point as the geohash, the endpoint as the hash plus a high Unicode character, Then we can order by the property that has that hash and then do start at, end at. But here's the problem. Let's imagine Kathy and Tim are next door neighbors And Tim does a search within this geohash. Even though Cathy is right next door, he's only going to get results inside of his geohash. So to get the true results, you would have to get all of the neighboring GeoHashes as well and then draw a radius around them to find anything within that radius. And there's a bunch of other little edge cases that you'll run into as well, which is why I decided to just create a library that handles all this stuff under the hood. It's called GeoFireX, and it uses RxJS and Firestore to make these queries possible. But don't worry, I didn't do any of the trigonometry myself. I left all that to an awesome library called Turf JS. And it's compatible with both Flat Earth and Round Earth theories. It's also compatible with any JavaScript framework long as it's using Firebase and RxJS. Let's go ahead and get started from a brand new Angular app. And then the first thing we'll do is install the Angular Google Maps package, which is a great component library if using Google Maps. From your Firebase project, you can go to the Google Cloud Platform console and enable the Google Maps JavaScript API. From there, we can install Angular Google Maps in our app as well as Firebase and GeoFire X. Now at this point, if you're using Angular or Ionic, I would recommend using the AngularFire 2 library. But the bare minimum thing you need to do is just initialize a Firebase app. So that should look something like this code here. Then you'll also want to initialize Angular Google Maps with your API key which you can do here in the app module. Now let's create a basic map with AGM which is super easy. The first thing we wanna do is go into our CSS and make sure we give it a width and height of something other than 0. Otherwise, you won't be able to see the map at all. After that, we can just declare an AGM map component and give it a starting latitude and longitude point. We can also drop in a marker and give it a latitude and longitude as well, And that will just pop up on the map at that point. What we'll do next is loop over a collection of documents in Firestore and render them on the map as these markers. One of the special things that GeoFireX does is that it saves data in a format that can be queried. In order to make Geo queries, you need to have an object on the document That contains a geohash and a geopoint. The library will format this for you automatically, but you can save multiple geopoints on a single document, so you can do Geo Queries against multiple parameters. So let's go ahead and make a query against this existing dataset. I'm gonna go ahead and import GeoFireX as well as our Firebase app. Then we can initialize GeoFireX by passing it a reference to our Firebase app. And then we'll also declare a property called points, which is an observable of the actual documents that we query. There are several variables that are needed to make a geo query. The first one is your center point, which can just be a latitude and longitude. You can create a geo hash with the library by calling the point method. It can do a bunch of other things like return geo JSON and calculate distance and bearing and things like that. Then the next variable that you'll need is the radius that you'll draw around the center point, which will always be in kilometers. Under the hood, the library uses turfjs to calculate the Haversine distance which also takes into account the curvature of the Earth. And lastly, we need to specify the object that contains the geo data because remember, a single document can have multiple geo points that can be queried against. Then the next thing we do is make a reference to the Firestore collection. This is just a wrapper for the main SDK that provides some additional functionality for geolocation. To perform a geo query, you can use the within method that will take in the center radius and field. And that returns an observable that you can just subscribe to, and it will stay in sync with any changes that happen in real time to that collection. But because we're using RxJS, we can do this in a little bit more of a dynamic way. For example, let's say, the user clicks a button that will expand the radius to a different value. For that, we could set up the radius as a behavior subject which itself is an observable that can have new values pushed to it. Then we'll define our observable points as the radius behavior subject that has been switch mapped to the actual observable geo query. And I would like point out that within returns a hot observable that is cached to the last value. That means you can have multiple subscribers to it and you will only be charged for the initial document read. So by setting this up with Switch Map, we can now change the radius and get a whole new query each time the user clicks a button. For example, we just need to call radius next And everything else will change reactively. Now we need to unwrap the observable of our locations. In Angular, we can do this very conveniently with the async pipe, but in other frameworks, you'd want to call subscribe on the observable and handle it accordingly. Inside of our AGM Marker will do an n g four loop and will loop over each point of points using the async pipe to unwrap it because it returns an observable array of document data. This gives us access to all of the data on each document, But it also returns some additional metadata that's specifically designed for building real time map features. For example, it returns the distance and bearing that this document was found at Relative to the query center point, which can only be figured out at runtime, you might query a collection of restaurants that are relative to a user's current GPS position on their phone, And the query metadata gives you the information needed to show the distance to that point to the user in the UI. And that will be by default on the query metadata on the return points. I have a premade demo that I'd use for integration testing and every point in the document is a specific distance and bearing from the center. And the actual gray circle is the radius of the query. And if we click on any of these points, we'll also see that query metadata which again is the distance and bearing. What's really cool about Firestore is everything is just real time by default. So imagine we have one of these documents that are being written to every seconds as the user's position moves, it will update in the UI like we see happening here with the blue marker. But as soon as it falls out of range, it disappears from the query and also the Why? There's a bunch of other little features that I've added to GeoVirX specifically for working with tools like Mapbox and Google Maps. If you find it useful, make sure to star it And please report any issues that you encounter when using it. I'm gonna go ahead and wrap things up there. Thanks so much for watching, and I'll talk to you soon.
The speakers discuss various Angular navigate apps and real world projects, including C consequence and GeoFinancialX using Angular Google Maps to create a real time geolocation feature. They recommend using the Angular app and the points method to create a query against an existing dataset and explain how to use the blockchain and other functions used in the app. A demo is then introduced for integration testing and a link is provided for any issues.