I am currently working on a firebase project. In this specific case we decided to use Firestore. For the sake of simplicity lets say we have multiple app users that post their location at a given time to the server so our document looks something like this
Footprint
-> username
-> createdAt (timestamp in milliseconds)
-> location (Geopoint)
Now a user should be able to search all users around him this is pretty easy to do by using a Query like:
firestore.collection('footprint')
.where('location', isGreaterThan: bounds['lower'])
.where('location', isLessThan: bounds['upper'])
bounds['lower'] and bounds['upper'] contain 2 Geopoints.
Now this would work but it gives me all Data near a geopoint. But the user only cares about it in a Chronological order. More like who were the last 100 Persons near this location. So it seems bad to send 10.000 Datasets to a User just to order them on the client side. There is usually no Wi-Fi available.
So i wanted to paginate the result and tried the following:
firestore.collection('footprint')
.where('location', isGreaterThan: bounds['lower'])
.where('location', isLessThan: bounds['upper'])
.orderBy('createdAt')
.limit(25)
Doesnt Work, Firebase enforces to orderBy 'location' first in this case. But the result of
firestore.collection('footprint')
.where('location', isGreaterThan: bounds['lower'])
.where('location', isLessThan: bounds['upper'])
.orderBy('location')
.orderBy('createdAt')
.limit(25)
doesnt help me it would show a dataset from 2017 first if it is right next to my current location.
So I thought about alternative and found the following:
- Clustering the locations
I thought i could cluster the locations like mapping all locations from 17.13-17.17 to 17.15 and then i could use an equals Query to get the Data i want.
firestore.collection('footprint')
.where('location', isEqual: bounds['closest'])
.orderBy('createdAt')
.limit(25)
But now i got the problem what if the users wants everything in an 100 km radius i would than have to do a huge amout of queries. Think about using 5 km clusters it would be 40*40 queries for all clusters in a 100km radius. And even then i would have problem to limit this data, since i care for chronological order and i would still have to send about 10.000 Datasets to the user.
- Using an additional Date (or something similiar) Field
I have the feeling that this is the closest i came to find a real solution for my problem
Footprint
-> username
-> createdAt (timestamp in milliseconds)
-> createdSearch (String looks like 2018-06-14)
-> location (Geopoint)
I could now Query the Data for a given Day like
firestore.collection('footprint')
.where('createdSearch',isEqual:'2018-06-14')
.where('location', isGreaterThan: bounds['lower'])
.where('location', isLessThan: bounds['upper'])
.orderBy('location')
This works but i would have to send additional queries for each day i want and i would have to order the data on the client side so no limit possible. If i have a lot of data i would also need to make my search field more explicit like '2018-06-14 12:00'. But then i would have to send a lot more queries ...
3 Trying to combine geopoint and timestamp into one Field
this should work in theorie, if i find a way to combine both values into one field that would allow to query them and order them with the same field this would work. But i have no idea how to do this.
I have the feeling that this should be a common problem , i found some other questions about Range Queries and ordering by other fields, but not with geolocations involved.
So what is the generell way to query for datasets near a given location and get them back by chronological order using Firestore ?
I should also mention that i dont want the user to wait for 30 Seconds so it should be a fast solution if possible. If other technologies(firebase) or data structures are necessary, that's ok too.