Since native GeoQueries are not yet supported, I've thought of a possible solution but would like to know of its validity and effectiveness.
What I want: I have a collection of about 2000 documents, each containing a Geopoint. I would like to query for example, the closest 20 documents to the users current location.
Possible Solution: Can I create another document in the collection and have that as my 'index'. Each field name would be the String of each documents ID. The value of each field would be the corresponding Geopoint. I would then only need 1 read operation when the app is opened... Can I then use a function to work through the 2000 document fields to calculate and order the distance of each location from the user? Finally, could I then take the closest 20 results and then just create a listener and pull only those results?
Edit: Have attempted my suggestion. Gave up after running into constant issues. I got the whole index document working, and was able to download it, arrange it to find the closest locations and the relevant doc id. However I had a lot of issues with using the array of doc IDs to set listeners to. I used a for loop to loop through each ID in the array and set a listener for each, but it only ever did the first one and random crashes kept happening. Also I noticed it took a fair bit longer to get the doc.... So, I decided to ditch the high accuracy solution and just query the geopoints to find locations within a square around the user.
I think that the easiest way will be query using the Firestore Geopoints, you can achieve it doing this:
fun Query.getNearestLocation(latitude: Double, longitude: Double, distance: Double): Query {
// ~1 mile of lat and lon in degrees
val lat = 0.0144927536231884
val lon = 0.0181818181818182
val lowerLat = latitude - (lat * distance)
val lowerLon = longitude - (lon * distance)
val greaterLat = latitude + (lat * distance)
val greaterLon = longitude + (lon * distance)
val lesserGeopoint = GeoPoint(lowerLat, lowerLon)
val greaterGeopoint = GeoPoint(greaterLat, greaterLon)
val docRef = FirebaseFirestore.getInstance().collection("locations")
return docRef
.whereGreaterThan("location", lesserGeopoint)
.whereLessThan("location", greaterGeopoint)
}
It's also wrote on Kotlin. This code is a Kotlin translation from the code made by Ryan Lee on this post.