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.
Implementing OR in firestore query - Firebase firestore
Edit (November 2019)
Cloud Firestore now supports "IN" queries (announcement) which allows you to do a type of OR queries that look for documents with one of a few values on the same field.
For example for the query above:
db.collection('users')
.where('company_id', '==', companyId)
.where('role', 'in', ['Maker', 'Checker', 'Approver']);
Original answer
There is no "OR" query in Cloud Firestore. If you want to achieve this in a single query you will need a single field like maker_or_checker_or_approver: true
.
Of course you can always do three queries and join them on the client.
Firebase Firestore Query based on filters
Based on your requirement, you can still use comparison values like code below:
Firebase Web Version 8:
db.collection("users")
.where("age", ">", "25")
.where("location", "==", "chicago")
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
});
})
.catch((error) => {
console.log("Error getting documents: ", error);
});
Firebase Web Version 9:
const q = query(collection(db, "users"), where("age", ">", "25"), where("location", "==", "chicago");
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
});
You can use comparison value as much as you want using these operators (<
, <=
, >
, >=
). By using multiple where
queries, it provides you a query statement with logical AND
query. The only limitation are for logical OR
queries which on these documentation states:
Cloud Firestore provides limited support for logical
OR
queries. The in, and array-contains-any operators support a logicalOR
of up to 10 equality (==) or array-contains conditions on a single field. For other cases, create a separate query for each OR condition and merge the query results in your app.
UPDATE:
If you want to query 50 documents at the same time. You can query it using FieldPath.documentID() and "IN" query. See code below:
const docArray = [
// Array of Document IDs.
];
db.collection("users")
.where(firebase.firestore.FieldPath.documentId(), 'in', docArray)
.where("age", ">", "25")
.where("location", "==", "chicago")
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
});
})
.catch((error) => {
console.log("Error getting documents: ", error);
});
As I stated on my previous answer, this only works if the array is of less than 10 items (Firestore limitation). If you need more, you'll have to either batch the IDs, into smaller arrays and perform multiple queries. Check code I written below:
// Consists of 11 values
const docArray = [
'5fKmta1jgEiCQBZvSJ3Y',
'BubAGhg6IZbnzU70wdPf',
'FVEq9trqF2Hy8ROsAjeW',
'Nhz0pF2z3zw3aBcmnpqs',
'TYYDYyIiyhVuWp91h7OS',
'VDDiUGKkGnwrdo8jmDpb',
'VXnXEuNfrhUAM8UbZ2AH',
'XukTkr4XBey3yqAvFa3d',
'cSNI1NgHP8OEsDY66RBw',
'eCPc9F1bpS1qXD9WGKE2',
'eHdKQPhE7snnRjoWJzBK'
];
const chunkedArray = [];
const resArray = [];
var promises = [];
// Firestore query limit
size = 10;
for(var i = 0; i < docArray.length; i += size) {
chunkedArray.push(docArray.slice(i, i+size));
}
chunkedArray.forEach((chunked) => {
promises.push(
db.collection("users")
.where(firebase.firestore.FieldPath.documentId(), 'in', chunked)
.where("age", ">", "25")
.where("location", "==", "chicago")
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
resArray.push(doc.data());
});
})
.catch((error) => {
console.log("Error getting documents: ", error);
})
);
})
Promise.all(promises).then(() =>
// Returns merged data from forEach
console.log(resArray)
);
You can also simply iterate the IDs, and get() each document individually. Look example code below:
docArray.forEach((docId) => {
promises.push(
db.collection("users")
.where(firebase.firestore.FieldPath.documentId(), '==', docId)
// .where("age", ">", "25")
// .where("location", "==", "chicago")
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
resArray.push(doc.data());
});
})
.catch((error) => {
console.log("Error getting documents: ", error);
})
);
})
Promise.all(promises).then(() =>
// Returns merged data from forEach
console.log(resArray)
);
Cloud Firestore OR query
If you want to pass an array of strings to a filter to match any one of them for a given field, that's called an "in" query.
The API documentation for where() suggsets that you should use "whereIn" for that.
.where('owner', whereIn: users)
From the documentation on in
queries:
Use the
in
operator to combine up to 10 equality (==
) clauses on the same field with a logicalOR
.
How do I Query Firebase Firestore for a field of type Geopoint in Flutter?
A Firestore query can only contain range conditions (>
, >=
, etc) on one value. So you can filter on either the latitude or longitude of the coords
, but not on both in a single query.
If you want to perform geoqueries on Firestore at the moment, the common approach is to store an additional so-called geohash value in your document, which is a (rather magical) string value that combines latitude and longitude in a way that allows you to query them to filter on geographic blocks.
If you want to learn how this works, I recommend checking out this video on the topic: Querying Firebase and Firestore based on geographic location or distance.
If you want to implement this approach on top of Firestore, check out the documentation on implementing geoqueries on Firestore.
I also recommend checking out these previous questions on the topic:
- How to run a geo "nearby" query with firestore?
- How to filter Firestore collection data using function (for location distance filtering)
- Is there a way to use GeoFire with Firestore?
- Firestore multiple range query
Related Topics
Why Are There Two Build.Gradle Files in an Android Studio Project
Findviewbyid VS View Holder Pattern in Listview Adapter
Emulate Mifare Card with Android 4.4
Permanently Hide Navigation Bar in an Activity
Starting an Activity from a Service After Home Button Pressed Without the 5 Seconds Delay
Android - Open Resource from @Drawable String
How to Hide an Item from Recycler View on a Particular Condition
Android: Activity Getting Destroyed After Calling Camera Intent
Edittext with Number Keypad by Default, But Allowing Alphabetic Characters
How to Detect When Phone Is Answered or Rejected
Create Custom Notification, Android
How to Remove a Button or Make It Invisible in Android
How to Do a Simple Search in String in Firebase Database
How to Add a Fragment Inside a Viewpager Using Nested Fragment (Android 4.2)
Firebase Fcm Force Ontokenrefresh() to Be Called
Broadcast Receiver Within a Service
How to Change Endianness Mid-Execution on Arm (Android/Linux)