Reputation: 598
How would I get the most recent documents in Firestore, in a geolocation radius, sorted by time?
I have a solution to get all documents in a Firestore database that are within a specified geolocation radius.
I need these ordered by time. As you would imagine, in a place like Los Angeles, there could be 10,000 nearby posts, and my current solution just doesn't scale.
Here is my Firestore query in SWIFT 4:
var query = docRef.whereField("geo", isGreaterThan: lesserGeopoint).whereField("geo", isLessThan: greaterGeopoint)
This is good enough to get the closest posts to me. So then, once I have all the closest posts, I parse them and put them in an array, and sort the array as follows:
self.posts.sort(by: { $0.time > $1.time })
This works, however, I scale-tested with dummy data, and here are the results:
(N = amount of posts that are queried and loaded)
N LOAD TIME (average)
-----------------------------------
0 303 ms
1 323 ms
100 393 ms
500 637 ms
1000 1011 ms (1 second)
5000 10439 ms (10.4 seconds)
Anything beyond 1,000 nearby posts just isn't practical. I also can't limit the query to 1000 documents, because it's not sorted by time on the Firestore server, so it would just take 1000 random documents that are nearby, and sort those by time. But there may be a more recent post that didn't make the cut in that batch.
How do I find a solution to get most recent, nearby posts, and limit the query so that my app can scale.
Upvotes: 4
Views: 2112
Reputation: 4908
You should be able to achieve this by ordering with your time field and setting a limit on the number of documents returned.
The first .whereField
must contain the first orderBy
field (which in your case is time
). After your geo query parameters, order by the time field, then set a limit
of (for example) 10, to get the top 10 results.
query = docRef.whereField("time", isGreaterThan: 0).whereField("geo", isGreaterThan: lesserGeopoint).whereField("geo", isLessThan: greaterGeopoint).order(by: "time").limit(to:10)
If you are storing the time as a Cloud Firestore native timestamp (ISO8601), then you'll need to use whereField("time", isGreaterThan: "")
This particular solution doesn't work, because you cannot perform range queries on 2 separate fields as decribed in, Simple and Compound Queries - Query Limitations
Upvotes: 1