如何在 Firebase Firestore 中获取内部集合

Posted

技术标签:

【中文标题】如何在 Firebase Firestore 中获取内部集合【英文标题】:How to get inner collection in firebase firestore 【发布时间】:2022-01-15 04:48:57 【问题描述】:

我正在尝试在 firestore 中获取特定用户的设备令牌,该设备令牌存储在“clients”或“lawyers”集合中的令牌集合中。 当我从链中删除第二个 .collection("tokens") 时,我得到了用户对象,但是使用链中的令牌集合,我似乎无法获得任何用户(客户或律师) ) 回来,即使用户和它的令牌存在。我做错了什么

  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") 
    
     )

【问题讨论】:

【参考方案1】:

这一行

if (!snapshot.exists)

应该是:

if (snapshot.empty)

因为您在CollectionReference(返回QuerySnapshot)上调用get(),而不是在DocumentReference(返回DocumentSnapshot)上。

如果您在示例中从链中删除 .collection('tokens'),它确实有效,因为 DocumentSnapshot 确实有成员 exists,但 CollectionReference 没有。

在这里看看他们的成员:

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

然后:

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

作为建议,我过去常常混淆快照并遇到这个问题,因为使用的是 javascript 而不是 Typescript。所以我习惯于在文档上调用结果snap,在集合上调用snaps。这让我想起了我正在做什么样的回应。像这样:

// 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);
  

【讨论】:

非常感谢@maganap。工作得很好。如此接近的方法有很大的不同 我很高兴它有帮助。您能否将答案标记为已接受?谢谢!

以上是关于如何在 Firebase Firestore 中获取内部集合的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 中使用 Firebase Auth 和 Firestore

如何将图像上传到firebase存储然后将图像url存储在firestore中?

如何使用firebase-admin在firestore中将日期保存为时间戳?

如何在 Firebase Firestore 中获取内部集合

如何在 Swift 上将具有自定义 ID 的文档添加到 Firebase (Firestore)

如何将我的 Firebase 实时数据库转移到 Firebase Cloud Firestore