How to represent the data for threaded comments(along with comment voting) in mongodb?

For my blog, I want to incorporate my own commenting system without relying on the default wordpress commenting system. I need the comments module to utilize mongodb instead of mysql and the module needs support for the following:

  1. Threaded comments
  2. Comment Voting
  3. The votes on comments need to be aggregated per each comment author for the entire blog.

In this context, What is best way to represent the data in mongodb?

Related posts

Leave a Reply

2 comments

  1. Just store the comments as you want them represented on your blog. You want threaded/nested comments? Then store them in a nested fashion:

    postId: {
      comments: [
        {
          id: "47cc67093475061e3d95369d" // ObjectId
          title: "Title of comment",
          body: "Comment body",
          timestamp: 123456789,
          author: "authorIdentifier",
          upVotes: 11,
          downVotes: 2,
          comments: [
            {
              id: "58ab67093475061e3d95a684"
              title: "Nested comment",
              body: "Hello, this is a nested/threaded comment",
              timestamp: 123456789,
              author: "authorIdentifier",
              upVotes: 11,
              downVotes: 2,
              comments: [
                // More nested comments
              ]
            }
          ]
        },
        {
          // Another top-level comment
        }
      ]
    }
    

    The postId refers to the blog post to which the comments belong and has been used as the key (or _id in MongoDB) of the document. Each comment has a unique id, in order to vote or comment on individual comments.

    To get the aggregated votes, you’ll need to write map-reduce functions somewhere along these lines:

    function map() {
      mapRecursive(this.comments)
    }
    
    function mapRecursive(comments) {
      comments.forEach(
        function (c) {
          emit(comment.author, { upVotes: c.upVotes, downVotes: c.downVotes });
          mapRecursive(c.comments);
        }
      );
    }
    
    function reduce(key, values) {
      var upVotes = 0;
      var downVotes = 0;
    
      values.forEach(
        function(votes) {
          upVotes += votes.upVotes;
          downVotes += votes.downVotes;
        }
      );
    
      return { upVotes: upVotes, downVotes: downVotes };
    }
    

    I haven’t tested these functions and they don’t check for null values either. That’s up to you 🙂

  2. How about:

    • A single collection for all comments. Each comment object holds a reference to a parent comment object for threading and of course the a reference to the parent blog post.

    • Each comment object also has numeric vote count that can be updated using mongo’s atomic updates.

    • Each specific vote by a user would then be a reference to the comment’s id in the user’s object directly.