简体   繁体   English

在 firebase 9 中访问文档中的集合

[英]Accessing a collection in a document in firebase 9

I want to access a collection inside a document.我想访问文档中的集合。 I want to access the document in the posts collection that has a specific postId however, inside that document there is a collection called comments which I would like to access.我想访问具有特定postId的帖子集合中的文档,但是,在该文档中,有一个名为 comments 的集合,我想访问它。 I don't think the code that I did is correct though.我不认为我所做的代码是正确的。

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();
    }));
}

Screenshot of database:数据库截图: 在帖子集合下

评论收集

Inside your map function, you aren't returning the document's data.在您的map函数中,您没有返回文档的数据。

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

This means for as many comments as you have on a post, you'll just get an empty array of that length.这意味着对于与帖子一样多的评论,您只会得到一个该长度的空数组。 ie 3 comments -> setComments([undefined, undefined, undefined])即 3 条评论 -> setComments([undefined, undefined, undefined])

You can fix this by rewriting that instruction as one of:您可以通过将该指令重写为以下指令之一来解决此问题:

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

However, as you are dealing with an array of comments, you should also return the document ID of each comment in the data so you can use it as the key for rendering .但是,当您处理一组注释时,您还应该返回数据中每个注释的文档 ID,以便您可以将其用作呈现key

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

Other notes其他注意事项

Instead of using bothdoc() and collection() :而不是同时使用doc()collection()

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

you could use just collection() on its own:您可以单独使用collection()

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

This turns your function into:这会将您的功能变成:

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() })
  ));
}

To make it safer for use in React, you should wrap it in a useEffect to make sure that calling setComments is still valid once you have the 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]);

As the above block looks the same for most Firestore calls aside from what data you are setting consider using a Firebase hooks library or write your own so you can flatten it all to something like:由于除了您正在设置的数据之外,对于大多数 Firestore 调用,上面的块看起来都一样,请考虑使用 Firebase 钩子库或编写自己的库,以便您可以将其全部展平,例如:

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

According to your problem first collection is posts , id is staring with 228... and subcollection is comments .根据您的问题,第一个集合是postsid 以 228...开头,子集合是 comments Try out the code below by replacing your values.通过替换您的值来尝试下面的代码。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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