How to perform compound queries with logical OR in Cloud Firestore?
From the docs:
You can also chain multiple where() methods to create more specific queries (logical AND).
How can I perform an OR
query?
Example:
- Give me all documents where the field
status
isopen
ORupcoming
- Give me all documents where the field
status == open
ORcreatedAt <= <somedatetime>
Solution 1:
OR
isn't supported as it's hard for the server to scale it (requires keeping state to dedup). The work around is to issue 2 queries, one for each condition, and dedup on the client.
Edit (Nov 2019):
Cloud Firestore now supports IN
queries which are a limited type of OR
query.
For the example above you could do:
// Get all documents in 'foo' where status is open or upcmoming
db.collection('foo').where('status','in',['open','upcoming']).get()
However it's still not possible to do a general OR
condition involving multiple fields.
Solution 2:
With the recent addition of IN queries, Firestore supports "up to 10 equality clauses on the same field with a logical OR"
A possible solution to (1) would be:
documents.where('status', 'in', ['open', 'upcoming']);
See Firebase Guides: Query Operators | in
and array-contains-any
Solution 3:
suggest to give value for status as well.
ex.
{ name: "a", statusValue = 10, status = 'open' }
{ name: "b", statusValue = 20, status = 'upcoming'}
{ name: "c", statusValue = 30, status = 'close'}
you can query by ref.where('statusValue', '<=', 20)
then both 'a'
and 'b'
will found.
this can save your query cost and performance.
btw, it is not fix all case.
Solution 4:
I would have no "status" field, but status related fields, updating them to true or false based on request, like
{ name: "a", status_open: true, status_upcoming: false, status_closed: false}
However, check Firebase Cloud Functions. You could have a function listening status changes, updating status related properties like
{ name: "a", status: "open", status_open: true, status_upcoming: false, status_closed: false}
one or the other, your query could be just
...where('status_open','==',true)...
Hope it helps.