Skip to content
Advertisement

Change fields of documents in a collection Firestore periodically – Cloud Functions

I have a database structure like this:

Posts(collection) -> userID (document) -> Subposts (subcollection) -> document[isVisible: true]

We have different userIDs which means that each userID has a subcollection of different posts.

I want to set up a cloud function which periodically (every 2 minutes) checks all the documents in all the sub collections (Subposts) and if the field isVisible is true, then changes it to false.

This is what I did:

exports.changeIsVisibleFieldAfterDay = functions.pubsub
    .schedule("every 2 minutes").onRun((context) => {
      db.collection("Posts/{uid}/Subposts").get().then((snapshot) => {
        if (snapshot.data().isVisible == true) {
          snapshot.forEach((doc) => doc.update({isVisible: false}));
        }
      });
    });

I’ve set up the {uid} wildcard because I need to check in each document subcollection (Subposts).

This implementation doesn’t seem to work.

Advertisement

Answer

For firestore query you must provide valid documentID.

If you wish to check for all users subcollections, there are few other ways to get it done!

  1. Using collection query
  • Query the Posts collection > iterate over the users
  • Query Subposts with valid doc ID for each user > iterate over the subpost documents
  • Update the doc with {isVisible: false} based on condition
  1. Using collectionGroup query
  • Use collectionGroup query on Subposts collection. This will return all subPosts of each user
  • iterate over the document and update with {isVisible: false} based on condition

In your iteration snippet, the collection query returns QuerySnapshot and in this the iteration should be on the field docs, like below

snap.docs.forEach((doc) => {
    if (doc.data().isVisible == true) {
        doc.update({ isVisible: false });
    }
});

Note: I prefer to go with async/await with for..loop instead of .then(), as forEach won’t give expected result with their inner await calls.

Advertisement