0
votes

I am try make Google firebase cloud functions codelab (https://codelabs.developers.google.com/codelabs/firebase-cloud-functions/#9) work with Firestore (now it configure for realtime db).

I have issue with modify this original code for Firestore:

// Sends a notifications to all users when a new message is posted.
exports.sendNotifications = functions.database.ref('/messages/{messageId}').onCreate(
    async (snapshot) => {
      // Notification details.
      const text = snapshot.val().text;
      const payload = {
        }
      };
      // Get the list of device tokens.
      const allTokens = await admin.database().ref('fcmTokens').once('value');
      if (allTokens.exists()) {
        // Listing all device tokens to send a notification to.
        const tokens = Object.keys(allTokens.val());

        // Send notifications to all tokens.
        const response = await admin.messaging().sendToDevice(tokens, payload);
      }
    });

So far I have make:

// Sends a notifications to all users when a new message is posted.
exports.sendNotifications = functions.firestore.document(‘/userscollection/{uid}').onCreate(
  async (snapshot) => {

// Notification details.
const text = snapshot.val().text;
const payload = {
notification: {
}
 };

    // Get the list of device tokens.    
const allTokens = await admin.firestore().collection('users').where('FCMToken', '>', "").get()
.then(snap =>{
if (snap.empty) {
console.log('snap is empty');
return;
}
snap.forEach(doc => {
console.log(doc.id, '=>', doc.data());
});
})
 .catch(err => {
console.log('Error getting docs', err);
});

console.log('allTokens is: ', allTokens);

    if (allTokens.exists()) {
      // Listing all device tokens to send a notification to.
      const tokens = Object.keys(allTokens.val());
      // Send notifications to all tokens.
      const response = await admin.messaging().sendToDevice(tokens, payload);
    }
  });

This listen to /userscollection root collection correct so trigger cloud function. But function return error in console: TypeError: Cannot read property 'exists' of undefined at Object.<anonymous>

Also

console.log('allTokens is: ', allTokens); 

returns

allTokens is: undefined

In Firestore I am store tokens in user document in /users root collection. So I need modify codelab to get only ‘token’ field in all user document in /users collection.

Anyone help? Thanks!

1

1 Answers

0
votes

allToken is undefined; it being the evaluation of the following:

const allTokens = await admin.firestore()
                    .collection('users')
                    .where('FCMToken', '>', "")
                    .get()
                    .then(snap => {
                      if (snap.empty) {
                        console.log('snap is empty');
                        return;
                      }
                    ); 

The promise resolves to an undefined value because in the last thenable is return-ing undefined.

To correct this, you can chain a thenable that get the token from each document in the matched snapshot, return-ing that in an array.

const tokensFromQuerySnapshot = querySnapshot => {
  if(querySnapshot.empty) return [];

  const tokens = [];
  querySnapshot.forEach(queryDocumentSnapshot => {
    tokens.push(queryDocumentSnapshot.get('token'))
  });
  return tokens;
}

const allTokens = await admin.firestore()
                    .collection('users')
                    .where('FCMToken', '>', "")
                    .get()
                    .then(tokensFromQuerySnapshot);