How to get field from multiple-layer document in Firestore

I’m creating a website like Reddit by React and Firebase, and here is my data structure:

groups – random-uid – discussions – random-uid – subdiscussion-first – random-uid – subdiscussion – second – random-uid…….and so on.

I have written the code to create such structure.

    try {
      await FirebasePack
        .firestore()
        .collection('groups')
        .where('name', '==', group)
        .get()
        .then((querySnapshot) => {
          querySnapshot.forEach((doc) => {
            doc.ref.collection('discussions').doc().set({
              title: title,
              content: content,
              creator: creator,
              rating: 0,
              subdiscussions: 0,
              created_time: firebase.firestore.FieldValue.serverTimestamp()
            });    
          });
        });
    } catch (error) {
      console.log(error);
    }
    setPageLoading(false);
  };

My question is, when i’m going to show something like this:

enter image description here do i really need to repeat the pattern to get what fields on the fourth layer or deeper? If not, how could i get them more easily?

Answer

Creating a sub-collection for every nested reply may not be the best way since you are limited to a maximum depth of 100 subcollections. You can just create a sub-collection "messages" and store all messages in it. The structure would be like this:

groups -> {groupId} -> messages -> {messageId}
(col)       (doc)       (col)        (doc)

Each document (message) can be structured like this:

{
  id: "msgID",
  author: "msg_author_id",
  replyTo: "GROUP_or_msgID",
  ...otherFields
}

Here every message will have a field replyTo and can be either ID of message it’s replying to or just “GROUP”. If replyTo is “GROUP” then that means it’s a direct message in the group and if it’s an ID then it’s a reply.

It’s totally upto the flow of you app on how to paginate these messages i.e. load a few at start and load more if user requests so. For example, if a user wants to load replies for message with ID 1234, you can run this query:

const msgRef = firebase.firestore().collection("groups").doc(groupID).collection("messages")

const replies = await msgRef.where("replyTo", "==", "1234").get()

console.log(replies.docs.map(reply => ({id: reply.id, ...reply.data()})))