简体   繁体   中英

Can't access Firestore docs data after getting the doc object

I'm trying to fetch a single field value from a doc in a collection (stored in Firestore). The following function is called (by the triggered function) to perform this query and return the result.

Firestore data structure: Firestore 数据结构

After I fetch the query result into helper_token object - I cannot access the DATA (fields) in it. I tried many things, including:

helper_token[0].device_token;
helper_token.data().device_token;
JSON.stringify(helper_token);

Nothing works for me. The log always shows results like these:

helper_token = {}
helper_token = undefined

What am I missing? how can I get the device_token based on user ?

const admin = require('firebase-admin'); //required to access the FB RT DB
admin.initializeApp(functions.config().firebase);
const db = admin.firestore();

function getHelperToken(helperId) {
    //Get token from Firestore
    const tokensRef = db.collection('tokens');
    const helper_token = tokensRef.where('user', '==', 'TM1EOV4lYlgEIly0cnGHVmCnybT2').get();
    if (helper_token.empty) {
        functions.logger.log('helper_token EMPTY');
    }
    functions.logger.log('helper_token=' + JSON.stringify(helper_token));

    return helper_token.device_token;
};

For completeness, adding here the full calling function to the above function:

//DB triggered function - upon writing a child in the HElpersInvitations reference
exports.sendHelperInvitation = functions.database.ref('/HelpersInvitations/{helper_invitation_id}')
    .onCreate((snapshot, context) => {

        const helperId = snapshot.val().helperId;
        const title = snapshot.val().title;
        const body = snapshot.val().body;
        
        //Get the helper token by Id
        functions.logger.log('HelperID=' + helperId);
        functions.logger.log('getHelperToken=' + getHelperToken(helperId));
        const helper_token2 = getHelperToken(helperId);
        //Notification payload
        const payload = {
            notification: {
                title: title,
                body: body,
                icon: 'default',
                click_action: 'com.skillblaster.app.helperinvitationnotification' 
            }
        }
        
        //    //Send the notification
            functions.logger.log('helper_token [BEFORE sendToDevice]=' + helper_token2);
            return admin.messaging().sendToDevice(helper_token2, payload);


    });

You need to consider that the get() call is asynchornous and also that you get a list of documents and not a single doc . Can you try it with this code:

const admin = require("firebase-admin"); //required to access the FB RT DB
admin.initializeApp(functions.config().firebase);
const db = admin.firestore();

async function getHelperToken(helperId) {
  //Get token from Firestore
  const tokensRef = db.collection("tokens");
  const helperTokens = await tokensRef
    .where("user", "==", "TM1EOV4lYlgEIly0cnGHVmCnybT2")
    .get();
  let helper_token = "";

  helperTokens.forEach((token) => {
    helper_token = token.data();
  });

  functions.logger.log("helper_token=" + JSON.stringify(helper_token));

  return helper_token.device_token;
}

As the get() call in Firestore is asynchronous you need to use an asynchronous function. You can go through this article to know more about why Firebase APIs are asynchronous. Next when we query with the where clause in Firestore we get a list of documents even if there is only one document in the list. So we have to run a for loop to get the document inside the list of documents. Now as you are returning the value from an asynchronous function the return value will be a promise in pending state. So to get the value from the promise we need to use the then() block while calling the function.

Also I think the parameter helperId you are using in the function definition is not used anywhere in the function. Though it will not make a difference I would suggest you remove it if it is not required in the function.

So consider using the following code -

const admin = require(‘firebase-admin’);
admin.initializeApp(functions.config().firebase);
const db = admin.firestore();
 
async function getHelperToken() {
   //Get token from Firestore
   const tokensRef = db.collection(‘tokens’);
   const helper_token = await tokensRef.where(‘user’, ‘==’, ‘TM1EOV4lYlgEIly0cnGHVmCnybT2’).get();
 
   let helper_token_needed;
   helper_token.forEach((token) => {
     helper_token_needed = token.data();
   });
    console.log(helper_token_needed.device_token);
   return helper_token_needed.device_token;
 }
 
//when calling to the function use then() block to get the value as a promise is returned from asynchronous function
getHelperToken().then((value)=>{console.log(value)});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM