I want to build a Firebase Function that checks the "Friends" collection for "scheduled, ==, true" and then create a new document in the "Filings" collection with the "fname".
My Firetore is set up as follows:
Users (collection)
User IDs (documents)
|
|
Friends (collection)
Friends (documents with auto IDs)
[fname, scheduled: true/false]
|
|
Filings (collection)
Filings (documents with auto IDs)
Whenever I run the following function, I get an error stating that the doc is empty, even though it is not. I don't understand why that is. Hoping to get your advice
exports.scheduledFunction = functions.pubsub.schedule('every 5 minutes').onRun(async context => {
const task = await (db.collection('friends').where('scheduled', '==', true).get());
if (task.empty) {
console.log('doc is empty');
return;
}
task.forEach(element => {
console.log(element.id, '==>' , element.data());
});
});
Your friends collection is nested under a users document. Your db.collection('friends') code only accesses the top-level friends collection, which likely doesn't exist.
To access all friends collections, use:
db.collectionGroup('friends').where('scheduled', '==', true).get()
Related
So here I Have multiple sub-collections(subjects) in different doc's(grades) and I want to get all the sub-collections(subjects) documents(questions) at once I tried to get them by using Collection group queries the only problem which I am facing in my code sometime it returning all the doc's(questions) but sometimes not what is the issue
this is what i have tried
const getAllQuestions = (request,response)=>{
const subjects = ['Maths','English']
const questionsArray = []
subjects.forEach((subject,index)=>{
db.collectionGroup(subject)
.get()
.then((querySnapshot)=>{
querySnapshot.forEach((doc) => {
questionsArray.push({...doc.data(),id:doc.id})
})
if(index==subjects.length-1){
response.status(200).json({
status:200,
data:questionsArray,
length:questionsArray.length
})
}
})
})
}
If you don't want to get the subcollections from all grades, but only from one of them, you should not use a collection group query but instead specify the entire path to the collection you want to query/read:
db.collection('quizQuesDb/Grade 5/'+subject)
.get()
If you want to perform a query across all collections of a certain name under a specific path, see: CollectionGroupQuery but limit search to subcollections under a particular document
I would like to be able to delete all of a user's documents when deleting his account. I would like to do this on the backend side with cloud functions.
This similar post doesn't really answer my question (because I need to delete documents from multiple collections)
Here is the structure of my collections:
users
| uid
| email: userEmail#test.com
orders
| docId
| createdBy: uid
| …
| …
Here is my function:
const userDeleted = functions.auth.user().onDelete(user => {
// get user doc in users collection then remove it
const usersRef = db.collection("users").doc(user.uid);
usersRef.delete();
// get all user’s doc in orders collection
const ordersRef = db.collection("orders")
.where("createdBy", "==", user.uid)
.get()
.then(snapshot => {
snapshot.forEach(doc => {
ordersRef.doc(doc.id).delete();
});
})
.catch(err => {
console.log("Error getting documents", err);
});
return Promise.all(usersRef, ordersRef);
})
I need to iterate through the orders collection and find the documents that have the correct uid in the "createdBy" property and then delete them. I feel like I can't delete multiple things at once during onDelete, and I couldn't find anything concrete in the documentation.
Firebase logs return to me this error : object is not iterable (cannot read property Symbol(Symbol.iterator)) at Function.all when deleting a user.
The problem occurs on the following line: return Promise.all(ordersRef);
What am I doing wrong?
Promise.all expects an array of promises, so you need to put [] around the arguments:
return Promise.all([usersRef, ordersRef]);
I need to perform a query to get the oldest document in a sub collection.
I want to perform this query with few reads as possible.
DB description:
Based on Firebase.
Collection of devices. Each device holds a collection of call-backs. For a specific device I need to fetch the oldest call-back (call-backs has timestamp).
I think I know how to perform this query using the device Unique ID, But I want to do it by filtering by some field of the device, this field is also unique.
I was able to do it by querying the device with all of his call-backs but this will charge me for more reads then actually needed.
Query that works using ID:
admin
.firestore()
.collection("devices/{device_id}/callbacks")
.{order_by_timestamp}
.limit(1)
.get()
.then((data) => {
let callbacks = [];
data.forEach((doc) => {
callbacks.push(doc.data());
});
return res.json(callbacks);
})
.catch((err) => console.error(err));
If that field in devices collection is unique then you can fetch ID of that device first and then proceed with your existing logic as shown below:
async function getOldestCallback(thatFieldValue) {
const device = await admin.firestore().collection("devices").where("thatField", "==", thatFieldValue).get()
if (device.empty) return false;
const deviceId = device[0]["id"];
// existing function
}
This should incur 2 reads (1 for device document and 1 for oldest callback if it exist).
Additionally, since you are limiting number of docs to be returned to 1 then you can use [0] instead of using a forEach loop.
const callbacks = [ data[0].data() ]
I have an application in which I manage categories and subcategories.
So each time I delete a category, I have a mongoose middleware that deletes all the subcategories who belong to it.
schema.post('findOneAndDelete',
(category: CategoryDocument) => subcategoryModel.deleteMany({ category: category.id }))
That works fine when I delete just one category, what happens when I delete multiple?
I tried registering a deleteMany middleware like so:
schema.post('deleteMany',
(deletedQueryResult: any) => {})
But the deleteMany middleware just sends to my callback the result of the query (the time it took, number of deleted documents and some internal mongoose/mongodb properties).
Is there anyway I can get the deleted documents or their ids inside a mongoose middleware?
If not what are my other options here?
The deleteMany method returns an object with three fields:
n – number of matched documents
ok – 1 if the operation was successful, else 0
deletedCount – number of deleted documents
This is the same behaviour of the mongodb db.collection.deleteMany method.
I suggest you to add a static method to your model:
// Assign a function to the "statics" object of our schema
categorySchema.statics.deleteManyWithSubs = async function(catIds) {
const deleteQuery = /*your delete query using catIDs*/
const delRes = await this.deleteMany(deleteQuery);
catIds.forEach(id => {
await subcategoryModel.deleteMany({ category: id })
});
return true;
};
// Usage
categoryModel.deleteManyWithSubs(ids)...
I am having collection with some documents. Each document contains some arrays with strings. I want to know whether given string is there inside the specific document array. I have seen queries to find the documents by using array contains. But I have the document I just want to query whether the string exists inside that document array or not?
var dbRef = dbConnection.db.collection('posts').doc(req.body.post_id);
dbRef.where('likes', 'array-contains', req.body.user_id).get()
.then(data => {
console.log(data);
})
.catch(err => {
console.log(err);
})
I have a document with specific id. I know the document id. That document contains array named as likes. That array will store some strings. I want to know the whether the string exists or not inside that array or not? I am getting the following error
TypeError: dbRef.where is not a function
Then I tried without giving document id. It worked. It returned the documents. But I want to search inside the document array
Your dbRef points to a (single) document, and you can't query a document.
If you want to query the documents in the posts collection, you're looking for:
var dbRef = dbConnection.db.collection('posts');
dbRef.where('likes', 'array-contains', req.body.user_id).get()
...
You can query for both document ID and array contains with:
db.collection('books').where(firebase.firestore.FieldPath.documentId(), '==', 'fK3ddutEpD2qQqRMXNW5').get()
var dbRef = dbConnection.db.collection('posts');
dbRef
.where(firebase.firestore.FieldPath.documentId(), '==', req.body.post_id)
.where('likes', 'array-contains', req.body.user_id).get()
...
Alternatively, you can simply read the document with your original code, and then check client-side whether the array still contains the field:
var dbRef = dbConnection.db.collection('posts').doc(req.body.post_id);
dbRef.get()
.then(doc => {
if (doc.data().likes.indexOf(req.body.user_id) >= 0) {
... the post is liked by the user
}
})
.catch(err => {
console.log(err);
})