0

I have a ios location based app. A user needs to be able to see nearby users within a certain radius. is there a way to read the nearby user documents in batches so that i don't unnecessarily load too many documents that the user won't scroll through. So first show 20 nearby users. then when the user scrolls down and reaches the last (20th) item in the collection, load 20 more nearby users who have not already been loaded (still within the desired radius).

Something like this is easy to do if i'm just reading users in by their join/sign up date. but i'm not sure how to do this for a location based query.

Is my only option to query on a small radius and then increase the radius (which will load some of the documents that have already been loaded from the database in previous query) and then deal with duplicate documents on the client side?

caa5042
  • 166
  • 3
  • 16

2 Answers2

0

If you look at the documented solution for implementing geoqueries on Firestore, you'll see that it doesn't load the documents in order of proximity but in geohash blocks that looks like this:

enter image description here

The only workaround is indeed to start with a smaller radius to load the documents who are nearer, and expand the radius until you have loaded the required number of documents.

Also see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Yes I know. I don’t mind that it isn’t in exact order of distance. But I need to find a way to load in batches. With this expanding radius approach there will be a lot of duplicates and reloading documents that have already been loaded. There is no way around this? – caa5042 Aug 28 '23 at 16:34
  • Nope, there is no way around this when using GeoHash values - and that is currently the only way to do geofiltering on Firestore that I know of. – Frank van Puffelen Aug 28 '23 at 21:59
0

Geohashes are sort of an ancient technology. There are much more efficient ways to geoquery and one such way that pairs very nicely with Firestore is Uber's H3, Uber's open-source geospatial library that the Uber app itself uses. The library is written in C but C plays very nicely with Swift. I use it in an iOS app of my own and it does exactly what you're looking for.

The concept is simple. H3 tiles the globe in hexagons (of varying sizes from very small to very large depending on how granular you want that particular geoquery to be). The brilliance of this is that you can cluster these tiles together (around a central tile) to form larger hexagons. And if the individual tiles are small enough and the clusters they form are big enough, their coveragevery closely resembles circles. And this is why H3 is incredibly efficient because there is exceedingly little over-query when properly tuned.

And so to make this play nicely with Firestore, simply give each user's document a property that represents their proximity, which would be a cluster of tiles around the tile that represents their current location (this property would be an array of 64-bit integers as each tile is identified by a 64-bit integer). And so to make a geoquery, you ask H3 for the device's current tile by giving it lat-lng coordinates (which will return a 64-bit integer) and then ask Firestore to find all documents where this integer is contained in any other user's proximity array. And you can, of course, paginate these results which is what you're ultimately looking for.

trndjc
  • 11,654
  • 3
  • 38
  • 51