-
Notifications
You must be signed in to change notification settings - Fork 346
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Firebase Cloud Firestore #163
Comments
You can utilize geohashes. import g from 'ngeohash';
const store = firestore();
const addLocation = (lat, lng) =>
store
.collection('locations')
.add({
g10: g.encode_int(lat, lng, 24), // ~10 km radius
g5: g.encode_int(lat, lng, 26), // ~5 km radius
g1: g.encode_int(lat, lng, 30) // ~1 km radius
});
const nearbyLocationsRef = (lat, lng, d = 1) => {
const bits = d === 10 ? 24 : d === 5 ? 26 : 30;
const h = g.encode_int(lat, lng, bits);
return store
.collection('locations')
.where(`g${d}`, '>=', g.neighbor_int(h, [-1, -1], bits))
.where(`g${d}`, '<=', g.neighbor_int(h, [1, 1], bits));
}; Edit: Added some explanation. We convert from // Empire State Building, New York
const lat = 40.748676;
const lng = -73.985654;
// geohash with a 10 km radius resolution
g.encode_int(lat, lng, 24); // 6671229
// geohash with a 5 km radius resolution
g.encode_int(lat, lng, 26); // 26684916
// geohash with a 1 km radius resolution
g.encode_int(lat, lng, 30); // 426958662
// geohash at full resolution (most accurate)
g.encode_int(lat, lng, 52); // 1790794426114269
g.neighbors_int(26684916, 26); // 5 km
// [ 26684917,
// 26684919,
// 26684918,
// 26684915,
// 26684913,
// 26684891,
// 26684894,
// 26684895 ] This translates to something like: All locations in this 3x3 grid will have a geohash prefix that is in the range of This can be done with the realtime database as well. db
.ref('locations')
.orderByChild('g5')
.startAt(g.neighbor_int(h, [-1, -1], 26))
.endAt(g.neighbor_int(h, [1, 1], 26)); More info on how it's done + a ref. implementation (but for strings, for Redis) can be found here. Bits to radius table For more accurate results (as described here) you will need 9 listeners for each piece of the 3x3 grid that check for strict equality. const nearbyLocationsRefs = (lat, lng, d = 1) => {
const bits = d === 10 ? 24 : d === 5 ? 26 : 30;
const h = g.encode_int(lat, lng, bits);
const n = [h, ...g.neighbors_int(h, bits)];
const refs = [];
n.forEach(
(hash, i) =>
(refs[i] = store.collection('locations').where(`g${d}`, '==', hash))
);
return refs;
}; Edit: Added a note about possible duplicate results. In your let locations = [];
handleSnapshot = snapshot => {
const docs = [];
snapshot.forEach(doc => {
const data = doc.data();
data.id = doc.id;
docs.push(data);
});
locations = _.uniqBy(locations.concat(docs), 'id'); // lodash
}; |
To those who care, I had a PR for Firestore support but after a little conversation it was deemed not to be the appropriate time to bring it into the official library. However for any of you that are interested I have my |
Apparently we can execute a very basic text search operation in Firebase with the help of db
.collection('locations')
.add({ g: g.encode(lat, lng) });
// ..
locations = [];
const h = g
.encode(lat, lng)
.substring(0, 5);
// why 5? http://www.elastic.co/guide/en/elasticsearch/guide/current/geohashes.html
db
.collection('locations')
.orderBy('g')
.startAt(h)
.endAt(`${h}\uf8ff`)
.onSnapshot(handleSnapshot);
handleSnapshot = snapshot => {
const docs = [];
snapshot.forEach(doc => {
const data = doc.data();
data.id = doc.id;
docs.push(data);
});
locations = uniqBy(locations.concat(docs), 'id');
}; |
pls for android java |
We split the GeoFire libraries into two:
For documentation on how to use #1 with Cloud Firestore, see the documentation here: https://firebase.google.com/docs/firestore/solutions/geoqueries |
Geofire is an amazing library that can be used with the FIrebase Real-time Database,
is gonna be updated for the Cloud Firestore?
The text was updated successfully, but these errors were encountered: