3

I am trying to set up a firebase function that deletes all subcollections of a document when the document is deleted. Trough reading the documentation I have come to this code:

// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = require('firebase-functions');



// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions
//
// exports.helloWorld = functions.https.onRequest((request, response) => {
//  response.send("Hello from Firebase!");
// });

exports.DeleteColletionFunction = functions.firestore
    .document('exampleCollection/{exampleID}')
    .onDelete((snap, context) => {
        // Get an object representing the document prior to deletion
      // e.g. {'name': 'Marie', 'age': 66}
      const deletedValue = snap.data();
      deleteCollection()


    });



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);
  }

I have never worked before with cloud functions and therefore am not sure what I should do next. I see that in order to use the delete Collection function it is necessary to pass a database, collectionPath and batchSize. What would be the right values to pass in this case?

Should I use this line of code to get the firestore database?

const database = admin.firestore();

I am also getting some errors when copying this function from the documentation:

Expected '===' and instead saw '=='

[eslint] Avoid nesting promises. (promise/no-nesting) (parameter) snapshot: any

[eslint] Each then() should return a value or throw (promise/always-return) (parameter) resolve: any

Here is a screenshot to see the locations of the errors: enter image description here

Thank you for your help!

UPDATE:
I changed some things (adding a promise):

// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = require('firebase-functions');

const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);


// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions
//
// exports.helloWorld = functions.https.onRequest((request, response) => {
//  response.send("Hello from Firebase!");
// });

exports.DeleteColletionFunction = functions.firestore
    .document('exampleCollection/{exampleID}')
    .onDelete((snap, context) => {
        // Get an object representing the document prior to deletion
      // e.g. {'name': 'Marie', 'age': 66}
      const deletedValue = snap.data();
      const exampleID = context.params.exampleID;

      const BATCH_SIZE = 500;

      const database = admin.firestore();

      const commentsRef = database.collection('exampleCollection').doc(exampleID).collection("comments");

      commentsRef.doc('main').delete();

      const exampleRef = database.collection('exampleCollection').doc(exampleID).collection("exampleSubCollection");
      const deleteExamples = deleteCollection(database, exampleRef, BATCH_SIZE)
      return Promise.all([deleteExamples]);

   });



/**
 * Delete a collection, in batches of batchSize. Note that this does
 * not recursively delete subcollections of documents in the collection
 */
function deleteCollection (db, collectionRef, batchSize) {
    var query = collectionRef.orderBy('__name__').limit(batchSize)

    return new Promise(function (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(function (doc) {
        batch.delete(doc.ref)
      })

      return batch.commit().then(function () {
        return snapshot.size
      })
    }).then(function (numDeleted) {
      if (numDeleted <= batchSize) {
        resolve()
        return
      }
      else {
      // Recurse on the next process tick, to avoid
      // exploding the stack.
      return process.nextTick(function () {
        deleteQueryBatch(db, query, batchSize, resolve, reject)
      })
    }
  })
    .catch(reject)
  }

Now I am getting errors in the firebase console:

ReferenceError: exampleID is not defined at exports.DeleteColletionFunction.functions.firestore.document.onDelete (/user_code/index.js:26:66) at Object. (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:112:27) at next (native) at /user_code/node_modules/firebase-functions/lib/cloud-functions.js:28:71 at __awaiter (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:24:12) at cloudFunction (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:82:36) at /var/tmp/worker/worker.js:728:24 at process._tickDomainCallback (internal/process/next_tick.js:135:7)

Thanks for your help!

5
  • You are not structuring your function properly, you should handle all those tasks within one function Commented Jun 29, 2018 at 19:43
  • 1
    Also if you decide to call a function make sure that function returns a promise, so when you call the function you should use return deleteCollection(); Commented Jun 29, 2018 at 19:48
  • @d.mares I got most of this code from the firebase documentation, I got one part from the delete collections doc and the other from the Firestore triggers doc. I don't have any experience with cloud functions and just put some pieces together Commented Jun 29, 2018 at 19:52
  • @d.mares I updated my code, can you have a look at it? thanks Commented Jun 30, 2018 at 14:47
  • add const exampleID = context.params.exampleID; Commented Jun 30, 2018 at 15:11

1 Answer 1

1

Use instead admin.initializeApp();

Sign up to request clarification or add additional context in comments.

5 Comments

Ok this worked, now I am getting this error: ReferenceError: exampleID is not defined
add const exampleID = context.params.exampleID;
In the firebase functions console after function execution took 79 ms, finished with status: 'error' and I put const exampleID = context.params.exampleID; below const deletedValue = snap.data();
you are getting another error update the question with the error details
Ok, I updated the question again with the new error and code (btw thanks for your help)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.