0
votes

I'm successfully using a Firebase Cloud Function in Typescript to send a notification to users when a document in a Firestore collection is created.

However, because I store the same document at two different locations, it's sending the notifications out twice. I want the notification to be sent only once.

Is there a way to use another cloud function to get, say, the current user, and then use that in the query for my function that sends notification so it only looks for writes / reads in changes that happen for that specific user only?

Here is my code in Cloud Functions:

export const notificationOnMessageReceived = 
functions.firestore
    .document('users/{uid}/matches/{match}/messages/{message}') //HOW CAN I GET UID FROM ANOTHER FUNCTION AND USE IT HERE TO SPECIFY EXACTLY THE USER FOR WHICH IT SHOULD RUN?
    .onCreate(async snapshot => {

        const message = snapshot.get('Message');

        const token = snapshot.get('Device token receiver'); 

        console.log('token: ' + token); 

        const payload = {
            notification: {
                title: `New message`,
                body: `${message}`
            }
        };

        return fcm.sendToDevice(token, payload);
    });
1
Could you give more details on what you exactly want to do. "Can I get the uid": do you mean the uid of the user who created the document under users/{uid}/matches/{match}/messages/{message} OR the value of uid in this path? In any case, you should most probably be able to do all the processing in one Cloud Function. But we need more precise details in order to help you!Renaud Tarnec
If I get the user who created the document under users/{uid}/matches/{match}/messages/{message} it would still run twice since the same user creates both documents. So that won't work. If I could get the uid in the path and only run that code for one user then that would solve the problem. Right now since {uid} is undefined it runs for both users.The Fluffy T Rex

1 Answers

2
votes

I can see two possibilities:

1. Write the author uid in the documents

If you can write in the two documents the uid of the author, in your cloud Function you can check if this uid corresponds to the uid of the path.

Something like the following:

export const notificationOnMessageReceived = 
functions.firestore
    .document('users/{uid}/matches/{match}/messages/{message}') 
    .onCreate(async (snapshot, context) => {

         const newValue = snapshot.data();
         const authorId = newValue.authorId;

         const pathUid = context.params.uid;

         if (authorId === pathUid) {
         
             //proceed with the notification
 
         } else {
            return null;
         }

    })

Of, course this implies that, each time, the Cloud Function is triggered one time "for nothing". With regards to the price of a Cloud Function invocation, this is acceptable.

2. Write an extra document in a dedicated collection

This way, only one document would trigger the Cloud Function, but the drawback is obviously the extra write. In terms of price, it is higher than the previous solution (based on Blaze Plan pricing). You could regularly trigger a schedule Cloud Function that deletes the docs that were treated.


SIDE NOTE: You are apparently using an old version of the Firebase SDK for Cloud Functions, see https://firebase.google.com/docs/functions/beta-v1-diff#cloud-firestore. As of version 1.0 of the SDK, the event parameter for Firestore asynchronous functions is obsolete. It has been replaced by two new parameters: snapshot and context.