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.