Counting Comments

I’m trying to count the number of comments associated with each post (documentId) but I’m only able to count all comments for all posts (documentId).

Example: for comments on documents Post 1 and Post 2.
I’m only able to count ALL comments for both posts, and not individually like 10 comments for Post 1 and 20 comments for Post 2. Now it returns 30 comments for everything. Any idea?

Current code using package https://atmospherejs.com/tmeasday/publish-counts:

Server JS:

Meteor.publish('commentCount', function() {
    Counts.publish(this, 'comments', Comments.getCollection().find({
        status: "active"
    }));
});

Server/Client JS - Collection:

Comments.changeSchema(function (currentSchema) {
    currentSchema.status = {
        type: String,
        allowedValues: STATUSES,
        defaultValue:"active" };
});

STATUSES = ["flagged","active"];

Client JS:
Meteor.subscribe("commentCount");

Client HTML:
{{getPublishedCount 'comments'}}

Client HTML where comments attached to posts using _id via https://atmospherejs.com/arkham/comments-ui
{{> commentsBox id=_id}}

This shows all the total comment count (in case anyone wants to use it). But I’m hoping anyone can advise on how I can count for each documentId rather than all?

You’re not showing us how comments are associated with posts, but let’s assume each comment has a post documentId associated with it. Pass your documentId into your publish function, then use that to refine the returned cursor:

Meteor.publish('postCommentCount', function(documentId) {
  check(documentId, String);
  Counts.publish(this, 'comments', Comments.getCollection().find({
    documentId
    status: 'active'
  }));
});

Then wherever you subscribe to your posts comments, make sure you pass in the post documentId:

Meteor.subscribe('postCommentCount', documentId);
1 Like

@hwillson Thanks for replying! I’ve been struggling. I currently use the following method:

Client HTML where comments attached to posts using _id via https://atmospherejs.com/arkham/comments-ui
{{> commentsBox id=_id}}

I’ve checked and each comment is attached to “referenceId”. So I did this:

Meteor.publish('postCommentCount', function(referenceId) {
  check(referenceId, String);
  Counts.publish(this, 'comments', Comments.getCollection().find({
    referenceId
  }));
});

and

Meteor.subscribe('postCommentCount', referenceId);

But I still get this error in the console log - Uncaught ReferenceError: referenceId is not defined

This is a good example of data that should be denormalized and stored as a field on the document. Have a look at the implementation of socialize:commentable for a good reference.

@copleykj Like many others, socialize packages have the functionalities we want based on the awesome descriptions. But, like many others, I’m not an experienced developer and the documentation, lacking in a repo with an example, is really hard to use.

May I know if you have an idea on how I can implement it in this case? I’m looking for a simple case where I’ve a post and I want to attach commenting functionality to it.

Thanks in advance, your work on the socialize package is amazing and would be really helpful if there’re basic examples to work with.

I think in find shoud be key-value pairs, not string.

Meteor.publish('postCommentCount', function(referenceId) {
  check(referenceId, String);
  Counts.publish(this, 'comments', Comments.getCollection().find({
    referenceId: referenceId
  }));
});

I’m pretty sure shorthand assignment with es2015 enhanced object literal syntax is in use here.

is it required to install babel-plugin-transform-es2015-shorthand-properties ?

Enhanced object literals are supported without extra babel plugins.

You usually denormalize the data by incrementing the count for each comment. Say you have a document like this for a single post:

{
  "_id": "1234",
  "title": "Do you like waffles?",
  "content": "yeah we like waffles!",
  "comments": [],
  "commentCount": 0
}

So creating a post would be like:

Meteor.methods({
  'create post': function (doc) {
    check(doc, Match.ObjectIncluding({
      title: Match.Where(x => {
        check(x, String);
        return x.length > 5 && x.length < 64;
      }),
      content: String
    }));
    
    return Posts.insert(Object.assign(doc, {
      comments: [],
      commentCount: 0
    }));
  }
});

Then when you add a comment you can do something like this:

Meteor.methods({
  'add comment': function (postId, comment) {
    check(postId, String);
    check(comment, Match.ObjectIncluding({ })) // too lazy to type.

    return Posts.update(postId, {
      $push: { comments: comment },
      $inc: { commentCount: 1 }
    });
  }
})
1 Like

Yes, apparently the documentation is a bit technical, and there is a huge lack of demo repositories. Hopefully this can be solved in the near future.

In reality usage is extremely simple.

//First we create our model of a post using the socialize:base-model
let Post = BaseModel.extendAndSetupCollection("posts" /*this is the collection name*/);
//this also saves a reference to the collection on Meteor.collectionName for easy future access

//add liking and commenting capabilities
LikeableModel.makeLikeable(Post, "post");
CommentableModel.makeCommentable(Post, "post");


//Create a post to play with, using the save method of BaseModel to save it to the database
new Post({body:"The quick brown fox jumped over the lazy dog"}).save();

//Now we can pull Post instances from the database using find and findOne of the collection
let postInstance = Meteor.posts.findOne();

//Post instances have all the liking and commenting functions attached
postInstance.like(); //like the post (requires current user obviously)
postInstance.unlike(); //unlike the post
postInstance.likeCount() // get the count of the likes for this post -> 0

postInstance.addComment("Easy Peasy..."); //add a comment to the post
postInstance.commentCount(); // get the count of comments for this post -> 1

Hopefully this helps a bit. It really is dead simple to implement once you have your head wrapped around it.

socialize:base-model

@copleykj Thanks for your guide! I’m going to implement it and let you know how it works out. Do bear with me.

In fact I’ll definitely write a short guide from a perspective (step-by-step process) of a new developer on implementing these packages starting with (1) base (2a) commenting and (2b) likeable. I’ll create a pull request for your existing documentation on Github and you can see if you find it might be useful for anyone.

I was scouring forums, Github, Youtube and Google in general and it seems like a lot of people would benefit from a simple not-so-technical guide on your packages.

1 Like

Awesome, I look forward to a guide. If you need further assistance there are slack and gitter channels at meteor-socialize.slack.com and gitter.im/copleykj/socialize, the gitter channel will require an invite but there are more of us there so if you want to shoot me an email to copleykj@gmail I’ll hit you back with an invite.

1 Like