J.Ko
J.Ko

Reputation: 8731

Firebase cloud function: perform a query from document creation, then delete the results except the newly created one

Here are what I am trying to do with Firebase cloud function.

  1. Listen to document creation in a collection. (In this case, a collection named 'posts')
  2. Query based on the field of the new document. (In this case, 'uid' field)
  3. Delete all the documents returned by the query EXCEPT the original one. If the original one is the only one that satisfies the query, retain it.

The third step is a little bit tricky. What would be the syntax/code to delete all the documents except the original one?

Thought about deleting all the results and adding a new documents afterwards but this is inefficient and would trigger an infinite function invocations for sure.

Also thought about getting the specific reference for the newly created document and delete the documents that do not match this condition, but cannot find out the right syntax to use for firestore query/cloud functions operations.

Here is my code. What would be the code to fill in the empty lines? Any advice? Thanks!

exports.duplicationCheck = functions.firestore.document('posts/{postid}')
.onCreate((snap,context)=>{
    const data=snap.data();
    const uid=data.uid;
    return db.collection('posts').where('uid','==',uid).get()
    .then(querysnapshot=>{
        if (querysnapshot.docs.length>1) {
            //Code to delete the returned results except the newly created one? 
        }
        else {
            return null;
        }
    })
})

Upvotes: 0

Views: 225

Answers (1)

Renaud Tarnec
Renaud Tarnec

Reputation: 83103

You can get the document ID of the newly created document via context.params.postid, so you can proceed as follows, since a document ID is unique accross a collection:

exports.duplicationCheck = functions.firestore.document('posts/{postid}')
    .onCreate((snap, context) => {

        const newDocID = context.params.postid;

        const data = snap.data();
        const uid = data.uid;
        return db.collection('posts').where('uid', '==', uid).get()
            .then(querysnapshot => {
                if (querysnapshot.size > 1) {
                    const promises = [];
                    querysnapshot.forEach(doc => {
                        if (doc.id != newDocID) {
                            promises.push(doc.ref.delete());
                        }
                    })
                    if (promises.length > 0) {
                        return Promise.all(promises);
                    } else {
                        return null;
                    }       
                }
                else {
                    return null;
                }
            })
    })

You'll find some details on Promise.all() here.


Note that since Promise.all() returns "an already resolved Promise if the iterable passed is empty" you could avoid checking the length of the promises array and directly do return Promise.all(promises);...

Upvotes: 1

Related Questions