MichaelDaly's avatar

Count likes and comments

I am developing a site at the moment which allows people to create articles in a blog format.

A feature of the site allows other users to 'like' and 'comment' on the article.

I am wanting to count the number of likes and comments an article has and display the count in a summary at the top of the article page. (A bit like the way Jeffrey displays the number of comments on a forum post in the right side of the listing page)

Currently, if a user comments on an article, I post the comment to the Comments table. Similarly, if a user 'likes' an article, I post the like to the Likes table. Using my current architecture, it means I have to query the comments table and get the count, then query the likes table for the count each time an article is viewed.

I am wondering if a better architecture would be to add 2 columns (Counts, Comments) to the Articles table and add/remove an increment each time a user adds/removes a like or comment? The idea would then be to simply display the count in the article without having to query or join other tables.

If anyone can think of another way to do this or thinks the way I have suggested is a bad idea then I would love to hear your feedback.

Thanks in advance

0 likes
11 replies
MichaelDaly's avatar

Thanks for the reply. I am currently using the approach you suggested.

My concern with this is when the 'likes' and 'comments' table grows really large (as I expect) then it could hit the performance when a user views the article as it would have to go through 2 large tables and do a count of the related likes and comments.

So, my question was more around using a solution which would keep a counter on the article record itself as well as keeping the data in the like and comment table. This would mean that whenever I load an article I would simply select the field with the count rather than joining and counting on a potentially massive table and counting live.

I just needed to know if there were any better options than the approach I have suggested.

Thanks again

Morgon's avatar

With really strong indexes, it shouldn't be too much of a performance hit to count the number of comments or likes that are assigned to a particular article_id. Subqueries are useful things.

Having said that, if your queries end up too complicated (I've run into this problem counting messages in a conversation, for instance), I don't think there's anything wrong with keeping a counter if you just need to say 'Read x comments'.

The downside to this approach is that you have to keep those entity summaries within your article table. If you add support for pingbacks, for instance, and need to display those, then that's another field in your article table. Whether that's fine or not is up to you, but it's a valid thing to think about, especially after you have ten million articles in the table and now need to change the schema.

Benchmark! :)

austenc's avatar

I wouldn't worry about optimization too much at this point -- you can solve those problems down the road!

mantasmo's avatar

@Mike I had the exact same problem about a year ago and went with your solution (two extra columns in the posts table). I like to think of these as a form of "caching".

Don't think there's one correct answer here to be honest. I prefer this approach because it makes my classes so much cleaner.

1 like
Mathi's avatar

Hi Mike I am in similar situation, can u help to get a single query to get the count of likes and comments joining both likes and comments table

jlrdw's avatar

You could have another table that gets updated with counts.

rsands's avatar

Are you using eloquent and eager loading? I have found by using a manually drawn query and use select raw I can easily query and count 1million+ rows in milliseconds

Eloquent I find and all the relationship stuff is dead slow

sunergetic's avatar

@Mathi Not quite sure what your situation is, but i can give an approach that i use myself.

Lets say you have the following Models:

  • Article (id, title, body)
  • Like (id, article_id)
<?php namespace App;
    
class Article{
    public function likes(){
        return $this->hasMany(App\Like::class, 'article_id', 'id');
    }

    # Use this to count the likes
    public function getLikeCountAttribute(){
        return $this->likes->count();
    }
}

# Sample usage
$article = App\Article::first();
$article->like_count;

OR Different situation, let's say you can give X amount of stars per rating, and you want to get the total count of all the stars:

Lets say you have the following Models:

  • Article (id, title, body)
  • Rating(id, article_id, stars)
<?php namespace App;
    
class Article{
    public function ratings(){
        return $this->hasMany(App\Rating::class, 'article_id', 'id');
    }

    # Use this to count the likes
    public function getStarCountAttribute(){
        return $this->ratings->sum('stars');
    }
}

# Sample usage
$article = App\Article::first();
$article->star_count;
Benja's avatar
$data = Posts::join('likes', function($join){
        $join->on('likes.posts_id', '=', 'posts.id')->where('likes.status', '=', 
                     '1' )->where(post.status','active');
            })
                    ->groupBy('likes.posts_id')
                    ->orderBy( \DB::raw('COUNT(likes.posts_id)'), 'desc' )
                    ->select('posts.*')
                    ->paginate( '5' );

Please or to participate in this conversation.