【问题标题】:Accessing a collection in a document in firebase 9在firebase 9中访问文档中的集合
【发布时间】:2021-10-16 01:49:50
【问题描述】:

我想访问文档中的集合。我想访问具有特定 postId 的帖子集合中的文档,但是,在该文档中有一个名为 cmets 的集合,我想访问它。我不认为我做的代码是正确的。

const fetchComments = async() => { 
    const posts = doc(db, 'posts', postId);
    const comment_list = collection(posts, "comments");
    const snapshot = await getDocs(comment_list);

    setComments(snapshot.docs.map((doc) => { 
        doc.data();
    }));
}

数据库截图:

【问题讨论】:

  • 你能分享一下你的数据库集合结构的快照吗?
  • 刚刚发布了图片
  • 乍一看,您加载 cmets 的方式对我来说很好。有什么不好的地方?
  • 如果有错误请分享截图。您还可以在使用此数据的地方分享您的反应组件吗?
  • @FrankvanPuffelen 似乎就像缺少一个返回语句一样简单。

标签: javascript reactjs firebase google-cloud-firestore


【解决方案1】:

在您的 map 函数中,您不会返回文档的数据。

setComments(snapshot.docs.map((doc) => { 
    doc.data(); // <-- not returned!
}));

这意味着对于您在帖子中拥有的尽可能多的 cmets,您只会得到一个该长度的空数组。即 3 cmets -> setComments([undefined, undefined, undefined])

您可以通过将该指令重写为以下之一来解决此问题:

setComments(snapshot.docs.map((doc) => {
  return doc.data()
}));
setComments(snapshot.docs.map(
  (doc) => doc.data()
));
setComments(snapshot.docs.map((doc) => doc.data()))

但是,当您处理一个 cmets 数组时,您还应该返回数据中每个评论的文档 ID,以便您可以将其用作 key for rendering

setComments(snapshot.docs.map(
  (doc) => ({ key: doc.id, ...doc.data() })
));

其他说明

不要同时使用doc()collection()

const posts = doc(db, "posts", postId);
const comment_list = collection(posts, "comments");

您可以单独使用collection()

const comment_list = collection(db, "posts", postId, "comments");

这会将你的函数变成:

const fetchComments = async () => { 
  const comment_list = collection(db, "posts", postId, "comments");
  const snapshot = await getDocs(comment_list);

  setComments(snapshot.docs.map(
    (doc) => ({ key: doc.id, ...doc.data() })
  ));
}

为了使其在 React 中使用更安全,您应该将其包装在 useEffect 中,以确保在获得数据后调用 setComments 仍然有效。

useEffect(() => {
  let unsubscribed = false;

  if (!postId) {
    console.error(`Failed to load post comments! postId (${postId}) was falsy`);
    setComments(null);
    setLoading(false);
    setErrorMessage("Invalid post ID");
    return;
  }

  const comment_list = collection(db, "posts", postId, "comments");
  setLoading(true);

  getDocs(comment_list)
    .then((comment_list_snapshot) => {
      if (unsubscribed) return; // silently discard, outdated

      setComments(comment_list_snapshot.docs.map(
        (doc) => ({ key: doc.id, ...doc.data() })
      ));
      setErrorMessage(null);
      setLoading(false);
    })
    .catch((err) => {
      if (unsubscribed) return; // silently discard, outdated

      console.error("Failed to load post comments!", err);
      setComments(null);
      setErrorMessage("Comments could not be loaded.");
      setLoading(false);
    });

  return () => unsubscribed = true;
}, [db, postId]);

除了您设置的数据考虑使用 Firebase 挂钩库或编写您自己的数据之外,对于大多数 Firestore 调用,上述块看起来都一样,因此您可以将其全部展平为:

const [ comments_docs, comments_loading, comments_error ] = useFirestoreCollection(db, "posts", postId, "comments")

if (comments_loading)
  return null; // hide until loaded
if (comments_error) {
  console.error("Failed to load comments: ", comments_error);
  return (<div class="error">Could not load comments</div>)
}

const comments = comments_docs.map((doc) => ({ key: doc.id, ...doc.data() }));

return ({
  comments.map((commentData) => {
    return <Comment
      key={commentData.key}
      author={commentData.author}
      content={commentData.content}
      ...
    />
  })
});

【讨论】:

    【解决方案2】:

    根据您的问题,第一个集合是 postsid 正盯着 228... 子集合是 cmets。通过替换您的值来尝试下面的代码。

    db.collection('FirstCollection/' + id + '/DocSubCollectionName').get().then((subCollectionSnapshot) => {
        subCollectionSnapshot.forEach((subDoc) => {
            console.log(subDoc.data());
        });
    });

    【讨论】:

    • 如果还有问题我们再讨论吧!
    • 此答案对于 OP 请求的 Firebase Web SDK V9 无效(不使用兼容性库)。它也不执行与 OP 代码相同的功能。
    猜你喜欢
    • 2022-01-02
    • 2020-12-19
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    • 2018-10-21
    • 2019-08-16
    • 2023-01-27
    • 1970-01-01
    相关资源
    最近更新 更多