# GeoFireX
Realtime Geolocation with Firestore & RxJS
:point_right: [Live Demo](https://geo-test-c92e4.firebaseapp.com)
:tv: [Video Tutorial](https://angularfirebase.com/lessons/geolocation-query-in-firestore-realtime/)
## :checkered_flag: QuickStart
```shell
npm install geofirex
# peer dependencies
npm install rxjs firebase
```
### Initialize
The library is a lightweight client for the Firebase Web SDK that provides tools for wrangling geolocation data in Firestore. You need a [Firebase project](https://firebase.google.com/docs/storage/web/start) to get started.
```ts
// Init Firebase
import * as firebase from 'firebase/app';
firebase.initializeApp(yourConfig);
// Init GeoFireX
import * as geofirex from 'geofirex';
const geo = geofirex.init(firebase);
```
### Write Geo Data
Next, add some geolocation data in your database. A `collection` creates a reference to Firestore (just like the SDK), but with some extra geolocation tools. The `point` method returns a class that helps you create geolocation data.
```ts
const cities = geo.collection('cities');
const point = geo.point(40, -119);
cities.add({ name: 'Phoenix', position: point.data });
```
Calling `point.data` returns an object that contains a [geohash string](https://www.movable-type.co.uk/scripts/geohash.html) and a [Firestore GeoPoint](https://firebase.google.com/docs/reference/android/com/google/firebase/firestore/GeoPoint). It should look like this in your database. You can name the object whatever you want and even save multiple points on a single document.

### Query Geo Data
Now let's query Firestore for _cities.position within 100km radius of a centerpoint_.
```ts
const center = geo.point(40.1, -119.1);
const radius = 100;
const field = 'position';
const query = cities.within(center, radius, field);
```
The query returns a realtime Observable of the document data, plus some useful metadata like _distance_ and _bearing_ from the query centerpoint.
```ts
query.subscribe(console.log);
// [{ ...documentData, queryMetadata: { distance: 1.23232, bearing: 230.23 } }]
```
You now have a realtime stream of data to visualize on a map.

## :notebook: API
### `collection(path: string, query? QueryFn)`
Creates reference to a Firestore collection that can be used to make geo-queries and perform writes If you pass an optional Firestore query function, all subsequent geo-queries will be limited to this subset of documents
Example:
```ts
const collection = geo.collection('cities');
```
#### Performing Geo-Queries
`collection.within(center: GeoFirePoint, radius: number, field: string)`
Query the parent Firestore collection by geographic distance. It will return documents that exist within X kilometers of the centerpoint.
Each doc also contains returns _distance_ and _bearing_ calculated on the query on the `queryMetadata` property.
**Returns:** `Observable