GBO
GBO

Reputation: 19

Get collection and its subCollection in firebase

I have tried to get all data related to the collection and its subCollection

I have firestore database like this

collection|->document|->subCollection|->document|-...
          |->field                   |->field

I have tried to follow get data once and data model . But didn't quite work.

Then I created separately two collection

Screams [
  {
    "screamId": "YzBK8AVG3Q3pEN7tB3AA",
    "body": "new first scream on user handle",
  },
  ...
]

Comments [
 {
   "screamId": "YzBK8AVG3Q3pEN7tB3AA",
   "commentId": "yKC6viq7NjcvA7PAZmrT",
   "body": "new first scream on user handle",
 },
 ...
]

The result I want finally:

{
 "screamId": "YzBK8AVG3Q3pEN7tB3AA",
 "body": "new first scream on user handle",
 "comments":[
   {
    "screamId": "YzBK8AVG3Q3pEN7tB3AA",
    "commentId": "yKC6viq7NjcvA7PAZmrT",
    "body": "new first scream on user handle",
   }
 ]
}

The code I used

exports.getScreamWithComments = (req, res) => {
  let screamData = {};

  const commentsDoc = db
    .collection("Comments")
    .orderBy("createdAt", "desc")
    .where("screamId", "==", req.params.screamId)
    .get();

  db.doc(`/Screams/${req.params.screamId}`)
    .get()
    .then((doc) => {
      if (!doc.exists)
        return res.status(404).json({ message: "scream not found" });
      screamData = doc.data();
      screamData.screamId = doc.id;

      return commentsDoc;
    })
    .then((data) => {
      console.log(data);
      screamData.comments = [];
      data.forEach((doc) => {
        screamData.comments.push(doc.data());
      });

      return res.status(200).json(screamData);
    })
    .catch((err) => {
      console.error(err);
      res.status(500).json({ error: err.code });
    });
};

What I want is still getting the same result above with the old firestore database's structure.

When I have tried a new database structure, I couldn't get the same result. It has appeared just scream collection.

Any help would be much appreciated!

Upvotes: 0

Views: 65

Answers (1)

Dharmaraj
Dharmaraj

Reputation: 50830

You are not handling the first promise. Also it might be better if you check existence of scream first before querying the comments. Try refactoring the code to an async function as shown below:

exports.getScreamWithComments = async (req, res) => {
  // async function             ^^^^^
  const screamDoc = await db.doc(`/Screams/${req.params.screamId}`).get()
  if (!screamDoc.exists) return res.status(404).json({ message: "scream not found" });

  const commentDocs = await db
    .collection("Comments")
    .orderBy("createdAt", "desc")
    .where("screamId", "==", req.params.screamId)
    .get();

  const screamComments = commentDocs.docs.map(d => ({id: d.id, ...d.data()}))

  const screamData = {
    screamId: screamDoc.id,
    comments: screamComments
  }

  return res.status(200).json(screamData);
}

Upvotes: 1

Related Questions