If I have a simple collection such as:
Fruits:
Banana:
title: "Banana"
vitamins: ["potassium","B6","C"]
Apple:
title: "Apple"
vitamins: ["A","B6","C"]
And if I want to search fruits that contain vitamin B6, I would do the following:
db.collection("Fruits").whereField("vitamins", arrayContains: "A").getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in querySnapshot!.documents {
print("\(document.documentID) => \(document.data())")
}
}
}
And that would show me all the Fruits in my collection that contain the vitamin A. However, how would I be able to search fruits that contain multiple vitamins, say vitamins B6 and C? I cannot simply search ["B6","C"]
as it would then be looking for an array as opposed to independent strings.
Is this even possible in Cloud Firestore? If not is there any alternative way to do this?
There is no way to do multiple array-contains queries like you're asking in Firestore. You can, however, combine as many
where
conditions as practically possible. Therefore, consider this:Firestore.firestore().collection("Fruits").whereField("vitamins.potassium", isEqualTo: true).whereField("vitamins.b6", isEqualTo: true)
This, however, does not allow you to do a clean
or
search, justand
. To query for fruits with vitamin-x or vitamin-y, you'd have to get more creative. Furthermore, this approach should not be used in situations where there are "a lot" of possible values and they need to be combined with compound queries. That is because Firestore does not permit more than 200 composite indices and each composite index would need to specify the exact vitamin. For example, you'd have to create an individual composite index forvitamins.b6
,vitamins.potassium
, etc. and you only have 200 total.It would be tempting to to look for documents that match multiple conditions, by chaining the conditions in the query:
But the documentation on compound queries suggests that you cannot currently have multiple arrayContains conditions in a single query.
So, it is not possible with what you have today. Consider instead using a map structure instead of an array:
Then you could query like this:
There is no way in Firestore to query a Firestore database with more than one
arrayContains
. If you will use more than one, an error like this might occur:If you need to filter on more than one vitamins, you'll need to change the logic of structuring your database by creating a property for each individual vitamin that you have and then chain
.whereField()
function calls. I know it sounds a little weird but this is how Cloud Firestore works.Your schema should like this:
To find all the fruits with
potassium
,B6
andC
vitamins, you should use a query that looks like this: