Home > database >  How to get inner collection in firebase firestore
How to get inner collection in firebase firestore

Time:12-11

I'm trying to get the device token of a particular user in firestore which is stored in tokens collection inside either "clients" or "lawyers" collection. When i remove the second .collection("tokens") from the chain i get the user object back but with the token collection in the chain i just can't seem to get any user (client or lawyer) back, even though the user and it's token exist. what am i doing wrong

  exports.onReceiveChatMessage = functions.database
  .ref("/messages/{uid}")
  .onCreate(async (snapshot, context) => {
    const newMessage = snapshot.val();
    console.log("NEW_MESSAGE", newMessage);
    const senderName = newMessage.sender_name;
    const messageContent = newMessage.content;
    console.log("SENDER'S_NAME", senderName);
    console.log("MESSAGE_BODY", messageContent);
    const uid = context.params.uid;
    console.log("RECEIVERS_ID", uid);

    if (newMessage.sender_id == uid) {
      //if sender is receiver, don't send notification
      console.log("sender is receiver, dont send notification...");
      return;
    } else if (newMessage.type === "text") {
      console.log(
        "LETS LOOK FOR THIS USER, STARTING WITH CLIENTS COLLECTION..."
      );
      let userDeviceToken;
      await firestore
        .collection("clients")
        .doc(uid)
        .collection("tokens")
        .get()
        .then(async (snapshot) => {
          if (!snapshot.exists) {
            console.log(
              "USER NOT FOUND IN CLIENTS COLLECTION, LETS CHECK LAWYERS..."
            );
            await firestore
              .collection("lawyers")
              .doc(uid)
              .collection("tokens")
              .get()
              .then((snapshot) => {
                if (!snapshot.exists) {
                  console.log(
                    "SORRY!!!, USER NOT FOUND IN LAWYERS COLLECTION EITHER"
                  );
                  return;
                } else {
                  snapshot.forEach((doc) => {
                    console.log("LAWYER_USER_TOKEN=>", doc.data());
                    userDeviceToken = doc.data().token;
                  });
                }
              });
          } else {
            snapshot.forEach((doc) => {
              console.log("CLIENT_USER_TOKEN=>", doc.data());
              userDeviceToken = doc.data().token;
            });
          }
        });
      // console.log("CLIENT_DEVICE_TOKEN", userDeviceToken);
    } else if (newMessage.type === "video_session") {
    }
     })

CodePudding user response:

This line

if (!snapshot.exists) {

should be:

if (snapshot.empty) {

because you're calling get() on a CollectionReference (which returns a QuerySnapshot), not on a DocumentReference (which returns a DocumentSnapshot).

If you remove the .collection('tokens') from the chain in your example, it does work because a DocumentSnapshot does have the member exists, but a CollectionReference doesn't.

Take a look at their members here:

https://googleapis.dev/nodejs/firestore/latest/CollectionReference.html#get

Then:

https://googleapis.dev/nodejs/firestore/latest/QuerySnapshot.html

As a suggestion, I used to confuse snapshots and got that problem because of working with Javascript instead of Typescript. So I got used to calling the result snap when called on a document, and snaps when called on collections. That reminds me of what kind of response I'm working on. Like this:

// single document, returns a DocumentSnapshot
const snap = await db.collection('xyz').doc('123').get();
if (snap.exists) {
  snap.data()...
}

// multiple documents, returns a QuerySnapshot
const snaps = await db.collection('xyz').get();
if (!snaps.empty) { // 'if' actually not needed if iterating over docs
  snaps.forEach(...);
  // or, if you need to await, you can't use the .forEach loop, use a plain for:
  for (const snap of snaps.docs) {
    await whatever(snap);
  }
}
  • Related