简体   繁体   中英

Can you check two different firestore collections before updating a document in each one?

I have been using firestore, cloud functions, and the Admin SDK to build a blog/forum. There is a forumPosts collection and a forumComments collection. Comments can can have sub-comments, therefore each comment in the forumComments collection has the ID of the Post and the ID of its Parent Comment (a comment directly on the post (top level) has a parentId = to the postId).

My problem is that when a comment is posted, I need to first check if the blog post exists, then if the parent comment exists, and if both conditions are true update the comment count for the post and the comment count for the parent comment... then add the new comment to the forumComments collection. The obvious answer is to preform each step one by one, but that would require 4 document reads (4 gets) and 3 document writes (2 updates and 1 add)... which would make adding a comment an expensive operation.

I do not have a very good handle on promises and am actively trying to learn more... but I just can't seem to figure this one function out. Is there a more efficent way to do what I am trying to do? Any and all help is greatly appreciated!

Here is the current structure of my function:

index.js (contains http request and routes)

app.post('/forumPost/:forumPostId/:parentId/comment', FBAuth, postOneForumComment);
exports.api = functions.https.onRequest(app);

forumPosts.js (contains the postOneForumComment function)

enter code hereexports.postOneForumComment = (req, res) => {
  if (req.body.body.trim() === '') return res.status(400).json({ comment: 'Must not be empty' });  //check if entry is empty

  const newComment = {
    body: req.body.body,
    createdAt: new Date().toISOString(),
    forumPostId: req.params.forumPostId,
    parentId: req.params.parentId,
    username: req.user.username,
    userImage: req.user.imageUrl,
    commentCount: 0,
    likeCount: 0
  };

db.doc(`/forumPosts/${req.params.forumPostId}`).get()
.then((postDoc) => {
  const promises = [];

    if (!postDoc.exists) {return res.status(404).json({ error: 'Post not found' });}    //check if the post exists

    db.doc(`/forumComments/${req.params.parentId}`).get()
      .then((comDoc) => {

          if (!comDoc.exists) {return res.status(404).json({ error: 'Comment not found' });}   //check if the comment exists

          const comProm = comDoc.ref.update({ commentCount: comDoc.data().commentCount + 1 });    //increment the comment count on the parent comment
          const postProm = postDoc.ref.update({ commentCount: postDoc.data().commentCount + 1 }); //increment the comment count on the post

          return promises.push(comProm, postProm);
      })
      .catch((err) => {
        console.log(err);
        return res.status(500).json({ error: 'Something went wrong during the comment retrival' });
      });

  return Promise.all(promises);
})
.then(() => {
  return db.collection('forumComments').add(newComment); //add the new comment
})
.then(() => {
  console.log("8");
  res.json(newComment);
})
.catch((err) => {
  console.log(err);
  res.status(500).json({ error: 'Something went wrong' });
 });
};

Consider just adding the newComment in your web server. You can update the comment counts asynchronously using a Cloud Function. That makes your web route just 2 reads and 1 write.

In the Cloud Function perhaps you can just assume the parentId and forumPostId already exist (ie the code that posted the comment did the necessary validation), and just do 2 writes using FieldValue.increment() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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