Dijiflex
Dijiflex

Reputation: 593

Firebase Scheduled Function to read Data from Firestore and then do some updaates

I am having trouble writing a scheduled function to read data from firestore. The function is successfully running every 1 minute but now the problem is reading the data from firestore. I am using async-await because I want to loop through the data after the read then do then so some update. Kindly help I am using firebase functions for the first time. Below is my function. I keep getting this error cannot read property map of undefined

exports.checkDefaultedPledges = functions.pubsub.schedule("every 1 minutes").onRun( async 
(context) => {
  console.log("This will be run every 2 minutes!");
  const time = new Date().getTime();
  const snapshot = db.collection("pledges").get();
  const res = await snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() }));
  console.log(res);

  return null;
});

Is it possible for me to write this function without using the .then()?

Upvotes: 0

Views: 905

Answers (1)

Renaud Tarnec
Renaud Tarnec

Reputation: 83058

The problem I am having is that no data is being returned when reading the data.

You need to use await when calling get(), since it is an asynchronous method.

On the other hand, you should not use await in const res = await snapshot.docs.map() since docs is a simple property (no asynchronicity here).


If you want to update all the docs in the pledges collection, you can use a batched write as follows:

exports.checkDefaultedPledges = functions.pubsub.schedule("every 1 minutes").onRun(async (context) => {

    const time = new Date().getTime();
    const snapshot = await db.collection("pledges").get();

    const batch = db.batch();

    snapshot.forEach(doc => {
        batch.update(doc.ref, { "updateTime": time });
    })

    return batch.commit();
});

Note that a batched write can contain up to 500 operations: so if you know your collection has/will have more than 500 docs, you should use Promise.all() as follows:

exports.checkDefaultedPledges = functions.pubsub.schedule("every 1 minutes").onRun(async (context) => {

    const time = new Date().getTime();
    const snapshot = await db.collection("pledges").get();

    const promisesArray = snapshot.docs.map(doc => doc.ref.update({ "updateTime": time }));

    return Promise.all(promisesArray);
});

Side note:

It is a best practice to use FieldValue.serverTimestamp() instead of using the JS Date(), especially when you are writing to Firestore from a client app. serverTimestamp "returns a sentinel used with set() or update() to include a server-generated timestamp in the written data".

Since a Cloud Function is executed by a server, it is not a must, but you could adapt your code as follows:

const time = admin.firestore.FieldValue.serverTimestamp();

Upvotes: 1

Related Questions