3

I have a firestore collection of the following documents:

[
  {
    start:       { geohash: 'u3qchtmpuy2d' },
    destination: { geohash: 'u3qcjvxfh9cs' },
    timestamp:   '28 June 2019 at 20:24:00 UTC+2',
    ...
  }
]

and I tried to query it like this (its Firestore Web SDK)

// 5-characters geohash is 4.89km × 4.89km
const start = 'u3qch';
const destination = 'u3qcj';
const timestamps = {
  min: firestore.Timestamp.fromDate(
    moment(someDateTime).subtract(10, 'minutes').toDate()
  ),
  max: firestore.Timestamp.fromDate(
    moment(someDateTime).add(10, 'minutes').toDate(),
  ),
};

firestore
  .collection('deliveries')
  .where('start.geohash', '>=', start)
  .where('start.geohash', '<', geohashEnd(start))
  .where('destination.geohash', '>=', destination)
  .where('destination.geohash', '<', geohashEnd(destination))
  .where('timestamp', '>=', timestamps.min)
  .where('timestamp', '<', timestamps.max)
  .get()

the combination of >= and < is from Firestore: query documents by startsWith a string, hence geoHashEnd() function (out of the scope of this question).

It resulted in the following error:

FirebaseError: Invalid query. All where filters with an inequality (<, <=, >, or >=) must be on the same field. But you have inequality filters on 'start.geohash' and 'destination.geohash'

My question: what is the best approach to query my firestore collection by two geohash strings and an additional field, at once?

wscourge
  • 10,657
  • 14
  • 59
  • 80

1 Answers1

5

According to the official documentation regarding query limitations:

Query limitations

Cloud Firestore does not support the following types of queries:

  • Queries with range filters on different fields, as described in the previous section.

So as you can see, Cloud Firestore can only do a range filter on a single field and not on multiple fields as you intended to do. The most reasonable explanation is that Firestore cannot guarantee its performance in this case. Firestore must be able to return all results of a query in a single stream.

To solve this, you'll have to query the database twice and combine the results of those queries client side. It's not perfect, since you need to query twice but I think it will do the trick.

Please also note, that querying using range filters on geohashes will not return very accurate results. For that, I recommend you see Frank van Puffelen's remarkable video regarding this topic:

Community
  • 1
  • 1
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Yeah, the video was my starting point and I do query by neighbors as well. Can you recommend any database for my use-case? – wscourge Jun 06 '19 at 17:44
  • Questions asking us to recommend or find a book, tool, software library, tutorial or other off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers. – Alex Mamo Jun 06 '19 at 17:46
  • IMHO, I recommend you go ahead and query the database twice, it won't have a problem. – Alex Mamo Jun 06 '19 at 17:47
  • In my case, it's not twice, its three times - `start`, `destination` and `timestamp`. I am interested only in the records in 20 minutes period of time - consider the scenario when my app is 4+ years old and I still query all of my old records from the same address. – wscourge Jun 06 '19 at 18:10
  • Oh, I understand. Not even three times is an issue when it comes to Firestore. If you are not comfortable with that, at beginning I suggest you first only do some test and see how it works. – Alex Mamo Jun 06 '19 at 18:15
  • I am using firestore. How can we use where conditions in this situation - fetch all the chat conversations where "(senderid == loggedinuserid and receiverid == 10) or (senderid == 10 and receiverid == loggedinuserid)"? kindly suggest. Thanks. – Kamlesh Jun 15 '21 at 20:04
  • @Kamlesh That's no problem at all, to use multiple `==` calls in a single query. – Alex Mamo Jun 16 '21 at 06:56
  • As we both know that multiple `.where()` can be used in query but how can use `or` condition with 2-2 `where` conditions? are you getting what I am saying. Please suggest. Thanks. – Kamlesh Jun 16 '21 at 07:18
  • @Kamlesh I might check also this [answer](https://stackoverflow.com/questions/56865294/nosql-model-structure/56869041#56869041) out. – Alex Mamo Jun 16 '21 at 07:20