Hey I am new to firebase cloud functions, and I want to order a collection, which is stored in firestore, by a field and then write in each document of the collection the 'position' (this should happen every 60 minutes). After reading the documentations and some suggestions from Stackoverflow I tried following approach.
exports.scheduledFunctionPosition = functions.pubsub.schedule('every 60 minutes').onRun((context) => {
return admin.firestore().collection("example")
.orderBy("number", "desc")
.get()
.then(querySnapshot => {
if (!querySnapshot.empty) {
for(let i =0;i<querySnapshot.size;i++){
var queryDocumentSnapshotTmp = querySnapshot.docs[i];
queryDocumentSnapshotTmp.ref.update({'position':i+1});
}
return null;
} else {
console.log("");
return null;
}
});
As my programming skills aren't too good, I tried it the easy way, but I think there is a problem with the asynchronous programming. This code works perfect for the documents with the highest numbers. But when there are too much documents, this function won't update the last documents. Is there a solution for this?
The .update() is also asynchronous - you likely need to wait for it, whether using .then() or switching to async/await. My personal style would write it like:
exports.scheduledFunctionPosition = functions
.pubsub
.schedule('every 60 minutes')
.onRun(async (context) => {
//will be returning a PROMISE
let QuerySnapshot = await admin.firestore().collection("example")
.orderBy("number", "desc")
.get();
return QuerySnapshot.empty
? (console.log(""), Promise.resolve(null))
: Promise.all( //Promise.all waits for all promises in an array to complete
//returns an array, but we use it for the array of promises
QuerySnapshot.docs.map(async (doc, index) => {
return doc.ref.update({'position':index+1}) //returns a promise
});
});
Returning the Promise makes sure the function waits for operations to complete.
Also note Cloud Functions have a hard time limit - default is 60 seconds. They can time out if you have too many records.