This question already has answers here:
How to query Cloud Firestore for non-existing keys of documents
(1 answer)
Firestore select where a field is not present [duplicate]
(1 answer)
Closed 15 days ago.
I'm looking to get all documents from Firestore where a field does not exist OR is marked false.
The practical purpose is a product database with each document as a product. Then each document may have a field to "hide" the document such as hide_product: true.
I was looking at the documentation in Firestore and I can't seem to get a case working to get all product documents EXCEPT the ones marked with a field hide_product: true.
https://firebase.google.com/docs/firestore/query-data/queries#query_operators
const productsRef = collection(firebaseStorage, firestoreDbName)
const q = query(productsRef, where("hide_product", "==", false))
const products = await getDocs(q)
I tested with 3 documents: 1 with field missing, 1 with field as true, 1 with field as false.
Firestore fields
Product marked hide == true
Product marked hide == false
Product with no field
Code query
where(hide, "==", true)
Shows
Shows
No
where(hide, "==", false)
No
Shows
No
where(hide, "!=", true)
No
Shows
No
where(hide, "!=", false)
Shows
Shows
No
It would seem that using the WHERE() function excludes any document with the missing fields as mentioned mentioned in the documentation.
Is there a way to get the documents where a field is missing or false?
Related
This question already has answers here:
How to use array-contains operator with an array of objects in Firestore?
(2 answers)
Firestore to query by an array's field value
(3 answers)
Query firestore array of objects
(2 answers)
Closed last month.
After reading a bunch of threads regarding trying to perform queries on fields with dynamic keys in a document, I have two questions.
Is it possible to perform the following "query" on my data model: "Get field where createdDate is equal or greater than todays date"?
Should I change the data model?
I have documents (test.com in the below image) that have fields where the key is dynamic (0, 1, 2, 3 and so on). Each field is a "map", which (correct me if Im wrong) contains an object. Each object have a "createdAt". I want to query all fields on "createdAt" and return all fields where "createdAt" is equal to or greater than todays date. So in my image, as of today it is the 12 of january, the field with the key "1" should be returned.
My query below doesn't work due to I don't "reach down to each field", would each document have just color, createdAt and domainName flattened It would have worked.
const domainsQuery = query(
collectionGroup(db, "domains"),
where("releaseAt", ">=", new Date())
);
It's not possible to fetch only some fields of a document in firebase. You always fetch all fields of a document. You can filter returned documents but not the fields of documents. You should probably adjust your model.
I recommend just creating an additional subcollection (name can be arbitrary) and making those dynamic keys into ids of subdocuments instead.
Is it possible to perform the following "query" on my data model: "Get field where createdDate is equal or greater than today's date"?
No, there is not. You cannot filter documents based on a single field property that exists inside an object, which is contained in an array. What you are looking for cannot be achieved using partial data.
If you need to filter based only on a particular field, then you should consider duplicating the data on which you want to perform the filtering and adding it to a separate array. In this way, you can query the collection using the array-contains operator.
Should I change the data model?
A possible solution would be to get all those objects out of the array and add them as separate documents inside a sub-collection. In that way, you can simply perform the desired query.
I have a collection named ABC and when I am running the following query in node(12 OR 14) it also returns documents which "r_o" doesn't exist in it.
const aRef = firebase.collection('ABC');
let querysnap = await aRef.where('r_o', '!=', false).limit(50).get();
I have around 900K documents in the 'ABC' collection. Most don't have the field at all, some have it with a value of true(boolean), So in most of the documents "r_o" doesn't exist at all and the query should not return those documents but it does.
So looks like the query ignores ('r_o', '!=', false) and simply returns all 900K documents in the collection.
To clarify, I want to get all the documents only and IF only the field value is true, I don't want to have the documents if the field value is false OR field doesn't exist.
Per firebase documentation and in their example:
citiesRef.where("capital", "!=", false);
This query does not return
city documents where the capital field does not exist. Not-equal (!=)
and not-in queries exclude documents where the given field does not
exist.
PS: I am using package firebase-admin v9.0.0
This question already has answers here:
Firebase Giving Failed Precondition Error
(1 answer)
Cloud FireStore : NativeFirebaseError: [firestore/failed-precondition] The query requires an index.?
(1 answer)
Cloud Firestore: FAILED_PRECONDITION: The query requires an index
(5 answers)
Closed 5 months ago.
This post was edited and submitted for review 5 months ago and failed to reopen the post:
Original close reason(s) were not resolved
In code that I wrote with the help of a video on YouTube (https://www.youtube.com/watch?v=7aDG3L-bTS8), my orderBy and where clauses are in conflict for some reason unknown to me. The following code works (presumably because I added manual indexing already):
// Query Rule Example
const rule = where("company", "==", "Super Pizza Magic")
// Ordering Example
const order = orderBy("creationTimestamp")
// Querying the Collection Using a Query Rule
const querier = query(reference, order)
As does this code:
// Query Rule Example
const rule = where("company", "==", "Super Pizza Magic")
// Ordering Example
const order = orderBy("creationTimestamp")
// Querying the Collection Using a Query Rule
const querier = query(reference, rule)
But THIS code causes the exception identified by Jason:
// Query Rule Example
const rule = where("company", "==", "Super Pizza Magic")
// Ordering Example
const order = orderBy("creationTimestamp")
// Querying the Collection Using a Query Rule
const querier = query(reference, rule, order)
Thus, I cannot seem to filter by company while ordering by creationTimestamp.
Can someone help me understand what I've done wrong here, please?
UPDATE: know the link suggested the video would contain such an error, but that was unfortunately not the case for me. Instead, I tried to manually create the index that the link I was supposed to have seen would have created by going to Indexing under the Firestore section in the Firebase Console, and that is how I was able to get the orderBy method to work properly... however, it still won't work if I try using both, as mentioned above.
FURTHER UPDATE: Someone closed my question and linked to irrelevant questions as the reasoning for doing so... those similar but slightly different errors and very different code situations do not contain obvious answers to my unique error. I would appreciate it if this were left open so my unique error could be addressed by someone who knows this situation well. Thanks.
This question already has answers here:
How to perform compound queries with logical OR in Cloud Firestore?
(12 answers)
Closed 3 years ago.
I have a project on Firebase Firestore and I want to execute a compound query between two documents under the same subcollection. I have already created the indexes that Firestore requires and the query executes perfectly if the fields are on the same document.
To exemplify my situation:
Take this structure:
- Users (root collection)
- User (document)
- userId
- username
- ...
--- Personalization (subcollection)
--- Alerts (document)
- myTags (array of strings)
- ...
--- Location (document)
- region (string)
- ...
I want to perform a query that first verifies if the user region (/Users/{userId}/Personalization/Location) is equal to a reference value. If so, I want it to verify if the array myTags (/Users/{userId}/Personalization/Alerts) contains a certain tag.
This is the closest I could get so far:
db.collectionGroup('Personalization').where('region', '==', 'California').where('myTags', 'array-contains', 'Macbook')
.get().then(querySnapshot => {
if (querySnapshot.empty) {
console.log('Result is empty');
} else {
console.log('Result found. ', querySnapshot.size, ' result(s).');
}
querySnapshot.forEach(doc => {
console.log(doc.id, ' => ', doc.data());
});
}).catch(error => {
console.error(error);
});
This query works perfectly if I have all my fields under the same document, like:
--- Personalization (subcollection)
--- Alerts (document)
- myTags (array of strings)
- region (string)
- ...
Also, I can make both queries work perfectly separately like this:
db.collectionGroup('Personalization').where('myTags', 'array-contains', 'Macbook').get().then(querySnapshot => {
querySnapshot.forEach(element => {
console.log('Search only by tag => ', element.id, ' => ', element.data());
});
Is there a way I can make the query work while still using two different documents under the same subcollection or I have obligatorily use the same document to make a compound query? Maybe there's some configuration on the index or something like that as well that I don't know about since I only followed the error link Firebase gives you when you first try a compound query to create the index.
Additional information:
This code is being developed for deploy on Firebase Functions and it triggers every time there's an onWrite event on a certain collection I have.
Also, if someone knows some good examples of compound queries on Firestore I would appreciate it. I read the documentation already and saw a couple of videos from the Firebase team explaining how Firestore works, but I feel the lack of more complex samples to grasp how it works in practice.
Firestore currently does not support logical OR type queries where you can provide more than one condition to match:
How to perform compound queries with logical OR in Cloud Firestore?
It only supports logical AND, as you've seen. When you provide two where clauses, the query will give you only documents that meet both conditions.
If you want to implement a logical OR for multiple conditions, you will have to perform a query for each condition separately, and merge the results in your client code. This means you will be doing two queries:
where('region', '==', 'California')
where('myTags', 'array-contains', 'Macbook')
Then waiting for both queries to finish and looking at the results of each one.
Your compound query defined with .where('region', '==', 'California').where('myTags', 'array-contains', 'Macbook') will not return the two different documents.
As explained in the documentation (link above) this query will only return the documents that match the two where clauses ("logical AND").
As explained in the same documentation:
Cloud Firestore does not support the following types of queries:
...
Logical OR queries. In this case, you should create a separate query for each OR condition and merge the query results in your app.
...
As discussed in the comments below your question, one solution is to add an extra regions field to the Alert document.
This question already has answers here:
MongoDB: update every document on one field
(4 answers)
Closed 3 years ago.
I have a very simple case. I want to update my collection every midnight.
Im using node-schedule:
schedule.scheduleJob('0 0 * * *', () => {
Users.updateMany();
});
All I want to do, is to loop over every document in my collection (Users) and then if User.created is false, I want to turn it into true.
In javascript it would be:
for (let user in Users) {
if (user.created === false) {
user.created = true;
}
}
How to do it in mongoose? Thanks!
Edit: The story is very simple, I just want to iterate over every element in my db using mongoose and if iterated element has field "created" === false, change it to true.
You can use updateMany() methods of mongodb to update multiple document
Simple query is like this
db.collection.updateMany(filter, update, options)
For more doc of uppdateMany read here
As per your requirement the update code will be like this:
User.updateMany({"created": false}, {"$set":{"created": true}});
here you need to use $set because you just want to change created from true to false. For ref. If you want to change entire doc then you don't need to use $set
You first need a query to find the documents you want to update. This is simply:
{"created": false}
Then you need an update query to tell mongo how to update those documents:
{"$set":{"created": true}}
You need to use the $set operator to specify which fields to change, otherwise it will overwrite the entire document. Finally you can combine these components into a single mongo call with an additional parameter to tell mongo we want to modify multiple documents:
User.update({"created": false}, {"$set":{"created": true}}, {"multi": true}, (err, writeResult) => {});
Mongoose tries to closely replicate the mongo API so all this information can be found solely within MongoDB's documentation: https://docs.mongodb.com/manual/reference/method/db.collection.update/