All Projects → codediodeio → Geofirex

codediodeio / Geofirex

🌐 📍 Geolocation Queries with Firestore & RxJS

Programming Languages

typescript
32286 projects

Projects that are alternatives of or similar to Geofirex

Geofirestore Js
Location-based querying and filtering using Firebase Firestore.
Stars: ✭ 436 (+10.1%)
Mutual labels:  firebase, firestore, geolocation
Angularfire Lite
⚡️ Lightweight library to use Firebase API 🔥 with Angular
Stars: ✭ 245 (-38.13%)
Mutual labels:  rxjs, firebase, firestore
Firebase Instagram
📸 Instagram clone with Firebase Cloud Firestore, Expo, and React Native 😁😍
Stars: ✭ 389 (-1.77%)
Mutual labels:  firebase, firestore
Node Firestore Import Export
Firestore data import and export
Stars: ✭ 271 (-31.57%)
Mutual labels:  firebase, firestore
Firestore Apollo Graphql
An example of a GraphQL setup with a Firebase Firestore backend. Uses Apollo Engine/Server 2.0 and deployed to Google App Engine.
Stars: ✭ 371 (-6.31%)
Mutual labels:  firebase, firestore
crisis-news-mapper
日本の災害関連ニュースをTwitterから収集して地図上にマッピングするFirebaseプロジェクト crisis.yuiseki.net
Stars: ✭ 13 (-96.72%)
Mutual labels:  geolocation, firestore
Pring
Cloud Firestore model framework for iOS - Google
Stars: ✭ 260 (-34.34%)
Mutual labels:  firebase, firestore
Vuefire
🔥 Firebase bindings for Vue.js & Vuex
Stars: ✭ 3,234 (+716.67%)
Mutual labels:  firebase, firestore
Angular Firebase App Starter
The starting point of the Angular and Firebase - Build a Web Application Course
Stars: ✭ 37 (-90.66%)
Mutual labels:  rxjs, firebase
Flutter programs
Experiments with Mobile
Stars: ✭ 308 (-22.22%)
Mutual labels:  firebase, firestore
Firestore Backup Restore
NPM package for backup and restore Firebase Firestore
Stars: ✭ 307 (-22.47%)
Mutual labels:  firebase, firestore
Firestoregoogleappsscript
A Google Apps Script library for accessing Google Cloud Firestore.
Stars: ✭ 352 (-11.11%)
Mutual labels:  firebase, firestore
app
Source code of intencje.pl website and mobile/desktop apps based on Angular, Firebase, and Capacitor.
Stars: ✭ 12 (-96.97%)
Mutual labels:  rxjs, firestore
React Admin Firebase
A firebase data provider for the react-admin framework
Stars: ✭ 269 (-32.07%)
Mutual labels:  firebase, firestore
Game Music Player
All your music are belong to us
Stars: ✭ 76 (-80.81%)
Mutual labels:  rxjs, firebase
Squanchy Android
Open source Android app for your conferences
Stars: ✭ 294 (-25.76%)
Mutual labels:  firebase, firestore
Gmscore
Free implementation of Play Services
Stars: ✭ 4,356 (+1000%)
Mutual labels:  firebase, geolocation
Angularfire
The official Angular library for Firebase.
Stars: ✭ 7,029 (+1675%)
Mutual labels:  rxjs, firebase
Rxfirebase
RxJS wrapper with extra goodies for the Firebase JavaScript SDK
Stars: ✭ 11 (-97.22%)
Mutual labels:  rxjs, firebase
Firesql
Query Firestore using SQL syntax
Stars: ✭ 304 (-23.23%)
Mutual labels:  firebase, firestore

GeoFireX

Realtime Geolocation with Firestore & RxJS. Query geographic points within a radius on the web or Node.js.

⚡️ QuickStart

npm install geofirex rxjs firebase

Initialize

The library is a lightweight extension for the Firebase Web and Admin JavaScript SDKs to provide tools for wrangling geolocation data in Firestore.

Web:

// Init Firebase
import firebase from 'firebase/app';
firebase.initializeApp(yourConfig);

// Init GeoFireX
import geofirex from 'geofirex';
const geo = geofirex.init(firebase);

Node.js with the Firebase Admin SDK:

const admin = require('firebase-admin');
admin.initializeApp();

const geo = require('geofirex').init(admin);

With Typescript:

import * as geofirex from 'geofirex'; 
const geo = geofirex.init(firebase);

Write Geolocation Data

Next, add some geolocation data in your database using the main Firebase SDK. You can add multiple points to a single doc. Calling geo.point(lat, lng) creates an object with a geohash string and a Firestore GeoPoint. Data must be saved in this format to be queried.

const cities = firestore().collection('cities');

const position = geo.point(40, -119);

cities.add({ name: 'Phoenix', position });

Query Geo Data

Query Firestore for cities.position within 100km radius of a centerpoint.

const center = geo.point(40.1, -119.1);
const radius = 100;
const field = 'position';

const query = geo.query(cities).within(center, radius, field);

Each hit returns a realtime Observable of the document data, plus some useful hitMetadata like distance and bearing from the query centerpoint.

query.subscribe(console.log);
// [{ ...documentData, hitMetadata: { distance: 1.23232, bearing: 230.23 }  }]

You now have a realtime stream of data to visualize on a map.

📓 API

query<T>(ref: CollectionReference | Query | string): GeoFireQuery<T>

Creates reference to a Firestore collection or query that can be used to make geo-queries.

Example:

const geoRef = geo.query('cities');

// OR make a geoquery on top of a firestore query

const firestoreRef = firestore().collection('cities').where('name', '==', 'Phoenix');
const geoRef = geo.query(firestoreRef);

within(center: FirePoint, radius: number, field: string): Observable<T[]>

const query = geoRef.within(center: FirePoint, radius: number, field: string)
        
query.subscribe(hits => console.log(hits))

// OR fetch as a promise

import { get } from 'geofirex';

const hits = await get(query);

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 hitMetadata property.

point(latitude: number, longitude: number): FirePoint

Returns an object with the required geohash format to save to Firestore.

Example: const point = geo.point(38, -119)

A point is a plain JS object with two properties.

  • point.geohash Returns a geohash string at precision 9
  • point.geopoint Returns a Firestore GeoPoint

Additional Features

The goal of this package is to facilitate rapid feature development with tools like MapBox, Google Maps, and D3.js. If you have an idea for a useful feature, open an issue.

Logging

Each query runs on a set of geohash squares, so you may read more documents than actually exist inside the radius. Use the log option to examine the total query size and latency.

query.within(center, radius, field, { log: true })

Logging GeoQueries

Geo Calculations

Convenience methods for calculating distance and bearing.

  • geo.distance(geo.point(38, -118), geo.point(40, -115)) Haversine distance
  • geo.bearing(to, from) Haversine bearing

toGeoJSON Operator

A custom RxJS operator that transforms a collection into a GeoJSON FeatureCollection. Very useful for tools like MapBox that can use GeoJSON to update a realtime data source.

import { toGeoJSON } from 'geofirex';

const query = geo.query('cars').within(...)

query.pipe( toGeoJSON() )

// Emits a single object typed as a FeatureCollection<Geometry>
{
  "type": "FeatureCollection",
  "features": [...]
}

Promises with get

Don't need a realtime stream? Convert any query observable to a promise by wrapping it with get.

import { get } from 'geofirex';

async function getCars {
    const query = geo.query('cars').within(...)
    const cars = await get(query)
}

Tips

Compound Queries

The only well-supported type of compound query is where. A geoquery combines multiple smaller queries into a unified radius, so limit and pagination operators will not provide predictable results - a better approach is to search a smaller radius and do your sorting client-side.

Example:

// Make a query like you normally would
const users = firestore().collection('users').where('status', '==', 'online');


const nearbyOnlineUsers = geo.query(users).within(center, radius, field);

Note: This query requires a composite index, which you will be prompted to create with an error from Firestore on the first request.

Usage with RxJS < 6.2, or Ionic v3

This package requires RxJS 6.2, but you can still use it with older versions without blowing up your app by installing rxjs-compat.

Example:

npm i [email protected] rxjs-compat

Make Dynamic Queries the RxJS Way

const radius = new BehaviorSubject(1);
const cities = geo.query('cities');

const points = this.radius.pipe(
  switchMap(rad => {
    return cities.within(center, rad, 'point');
  })
);

// Now update your query
radius.next(23);

Always Order by [Latitude, Longitude]

The GeoJSON spec formats coords as [Longitude, Latitude] to represent an X/Y plane. However, the Firebase GeoPoint uses [Latitude, Longitude]. For consistency, this library always requires to use the latter Firebase-style format.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].