How to Have Either or Wherefields for Firestore Query

Compound whereField query in Firestore (Swift)

I added this pod for more convenient work

pod 'FirebaseFirestoreSwift'

First way

If you want to get all chats with these 2 users
For this, you need to add new cross-field with all users in this chat

let searchTerm = channelReference.whereField("users", arrayContainsAny: [ID1, ID2])

Simple way with 2 differeent queries - user1: "Alex", user2: "Adam"

let searchTerm1 = reference
.whereField("user1", isEqualTo: "Alex")
.whereField("user2", isEqualTo: "Adam")

let searchTerm2 = reference
.whereField("user1", isEqualTo: "Adam")
.whereField("user2", isEqualTo: "Alex")

Documentation reference https://firebase.google.com/docs/firestore/query-data/queries#compound_queries

How to perform compound queries with logical OR in Cloud Firestore?

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.

Get Firestore document with OR query


I need the app to retrieve every document where their user ID is in either the target or sender fields

This is not possible, as Firestore does not allow OR conditions between fields.

The closest you can get is adding an array field to the document where you keep the UIDs of all participants, and then checking whether the UID you're looking for is in that array with an in operation:

friendsRef
.whereField("participants", arrayContains: "uidOfUser")

How to keep adding conditions to an existing Firestore query?

The following worked:

if easyOnly == true || cheapOnly == true || highProteinOnly == true || vegetarianOnly == true {

// Reset the query
db.collection("mealPlans").document().getDocument { (snapshot, error) in

self.query = db.collection("mealPlans")

// Refine the query based on the button taps
if easyOnly == true {
self.query = self.query
.whereField("isEasy", isEqualTo: true)
}

if cheapOnly == true {
self.query = self.query
.whereField("isCheap", isEqualTo: true)
}

if highProteinOnly == true {
self.query = self.query
.whereField("isHighProtein", isEqualTo: true)
}

if vegetarianOnly == true {
self.query = self.query
.whereField("isVegetarian", isEqualTo: true)
}

queryData()
}
} else {
db.collection("mealPlans").document().getDocument { (snapshot, error) in

self.query = db.collection("mealPlans")

queryData()
}
}

self.query = db.collection("mealPlans") helped reset the query when multiple buttons were pressed.

queryData() was implemented at the end of each query to submit the query after all .whereField parameters were set.

How to sort Firestore query results with whereField is using arrayContainsAny and in

After digging deeper through the client logic I found an issue that caused the sorting to not be applied client-side.

After fixing that I'm getting back the items sorted consistently!

Firestore OR query

It's not possible in Firestore to execute an OR query like the one you describe.

One solution is to denormalize your data (a very common approach in the NoSQL world) and add, to the document, an extra field which "concatenates" the two other fields, as follows:

{
/* ... */
ownerId: "id-1",
memberIds: [
"id-2",
"id-3",
"id-4"
],
ownersAndMemberIds: [
"id-1",
"id-2",
"id-3",
"id-4"
]
}

Then you can easily query the doc with

return collection('whatever')
.where('ownersAndMemberIds', 'array-contains', 'id-1');

Of course it requires that you maintain this array aligned with the other fields, but this is not difficult. Either you do it from your front-end when you update one of the two "main" fields, or through a Cloud Function which is triggered on any change to the doc.

Firestore query a document based on starts with in any of the 2 fields

You won't be able to do this in one query, because Firestore does not support logical OR queries that span multiple fields. What you can do instead is make two queries, one for name, and the other for username that do string prefix sorts (read other questions about that here, here, here). Then, after you do both queries, merge the results on the client to build the final list of results.

Firestore Queries Swift 4 for range

Cloud Firestore does not at present allow you to do multiple inequality filters. A workaround may be to run the first .whereField query, and then once you have your documents, filter your array for the second query.

    Firestore.firestore().collection("team")
.whereField("min", isGreaterThanOrEqualTo : filterMin)
.getDocuments { (snapshot, error) in
if let snapshot = snapshot {
for document in snapshot.documents {
let data = document.data()

//parse your data into an array of teams
}
}

let filteredTeams = teams.filter { $0.max < filterMax }
}


Related Topics



Leave a reply



Submit