Luiz
Luiz

Reputation: 459

Delete an entire collection through Cloud Functions

Delete collection through a function created in Cloud Functions

I need to delete an entire collection with multiple documents when a user is deleted, so I decided to create a function so that it fires whenever a user is deleted.

Below is the code.

Cloud Functions (index.js):

  exports.onUserDeleted = functions.auth.user().onDelete((user) => {
    deleteCollection(admin.firestore(), user.uid, 15);
  });

  function deleteCollection(db, collectionPath, batchSize) {
    var collectionRef = db.collection(collectionPath);
    var query = collectionRef.orderBy('__name__').limit(batchSize);

    return new Promise((resolve, reject) => {
      deleteQueryBatch(db, query, batchSize, resolve, reject);
    });
  }

  function deleteQueryBatch(db, query, batchSize, resolve, reject) {
    query.get()
        .then((snapshot) => {
          // When there are no documents left, we are done
          if (snapshot.size === 0) {
            return 0;
          }

          // Delete documents in a batch
          var batch = db.batch();
          snapshot.docs.forEach((doc) => {
            batch.delete(doc.ref);
          });

          return batch.commit().then(() => {
            return snapshot.size;
          });
        }).then((numDeleted) => {
          if (numDeleted === 0) {
            resolve();
            return;
          }

          // Recurse on the next process tick, to avoid
          // exploding the stack.
          process.nextTick(() => {
            deleteQueryBatch(db, query, batchSize, resolve, reject);
          });
        })
        .catch(reject);
  }

When attempting to perform the firebase deploy command --only functions the following error occurs:

65:11 warning Arrow function expected no return value consistent-return

65:18 warning Avoid nesting promises promise/no-nesting

69:11 error Each then() should return a value or throw promise/always-return

✖ 3 problems (1 error, 2 warnings)

What am I doing wrong?

How can I delete the entire collection when the user is deleted?

If you can post the above code with the logic that I should apply, I will be very grateful.

Upvotes: 4

Views: 2767

Answers (1)

Renaud Tarnec
Renaud Tarnec

Reputation: 83191

Do as follows:

const db = admin.firestore();

exports.onUserDeleted = functions.auth.user().onDelete((user) => {

    const collectionRef = db.collection(user.uid);

    var promises = [];

    return collectionRef.get()
    .then(qs => {
       qs.forEach(docSnapshot => {
         promises.push(docSnapshot.ref.delete());
       });
       return Promise.all(promises);
    })
    .catch(error => {
        console.log(error);
        return false; 
    });
});

As reflected by your code and as advised in the documentation (see excerpt below) you may delete the docs by batch if the collection is very large. I let you adapt the above code for this, if you consider it is necessary.

If you have larger collections, you may want to delete the documents in smaller batches to avoid out-of-memory errors. Repeat the process until you've deleted the entire collection or subcollection. Source: https://firebase.google.com/docs/firestore/manage-data/delete-data#collections

Upvotes: 9

Related Questions