简体   繁体   English

计算帖子的平均评分

[英]Calculating average rating on a post

I have the following entity: 我有以下实体:

post_id | post_title | post_body
-------------------------------------
1       | First post | Hello, world!

and would like to register ratings on the post, like so: 并希望在帖子上注册评分,例如:

rating_id | rating_user_id | rating_post_id | rating_rating
1         | 23             | 1              | 3.5

My main concern/question is, how I should retrieve the average rating for a post. 我主要关心的问题是如何获取帖子的平均评分。 I know I can do this by using an SQL query like so: 我知道我可以这样使用SQL查询来做到这一点:

SELECT AVG(rating_rating) FROM post_ratings WHERE rating_post_id = 2;

but I would have to call this query everytime I'd do $post->getAverageRating() - is this a big performance issue? 但是我每次执行$post->getAverageRating()都必须调用此查询-这是一个很大的性能问题吗? (keeping in mind that there could be thousands of ratings per post) (请注意,每个帖子可能会有数千个评分)

An alternative would be to store the average rating in a new column in the posts table and have a cron job calculate the average or something? 一种替代方法是将平均评分存储在posts表的新列中,并让cron作业计算平均值或其他内容?

What is the best way of going about this? 最好的方法是什么?

As for comparing performance- It depends on 至于比较性能-这取决于

  1. How static the ratings are.If you expect new ratings for existing posts, I would go with calculating them on the fly anyway. 评分的静态程度。如果您希望现有帖子有新的评分,那么无论如何我都会即时进行计算。
  2. How many posts you would need the ratings for as opposed to overall posts. 与整体职位相比,您需要多少个职位的评分。 If you have millions of posts and need the average rating only for a few thousands, it makes sense to do them separately also. 如果您有数以百万计的帖子,并且只需要几千条的平均评分,那么分开进行也很有意义。

This is an issue of efficiency 这是效率问题

If and which these ratings will stack to a large amount, it would be preferable to save the calculated average I would add 2 columns to the posts table, average_rating, total_ratings 如果这些评级会与之叠加,那么最好保存计算出的平均值,我会在posts表中添加2列,average_rating,total_ratings

ALTER TABLE posts ADD COLUMN average_rating DECIMAL (9,2);
ALTER TABLE posts ADD COLUMN total_ratings UNSIGNED (9) DEFAULT 0;

And populate them whenever a new rating is added, so you won't need a cron job Notice the order of the queries to calculate the average 并在添加新评分时填充它们,因此您不需要进行cron作业请注意查询的顺序以计算平均值

The MySQL + PHP code should be something like: MySQL + PHP代码应类似于:

    $query = "UPDATE posts SET total_ratings  = total_ratings + " . $rating_rating . " WHERE post_id = " . $post_id;
    $db->query($query);
    $query = "UPDATE posts SET average_rating = average_rating * (total_ratings -1 / total_ratings) + " . $rating_rating ." / total_ratings WHERE post_id = " . $post_id;
$db->query($query);

This way you can update the posts table immediately without any cron job 这样,您无需任何cron作业即可立即更新posts表

Database calls are expensive especially when you have to average every time. 数据库调用非常昂贵,尤其是在每次必须求平均值时。

You have the following options that are more optimal compared to your current solution. 与当前的解决方案相比,您拥有以下最佳选择。

  1. Have a column that calculates and stores the average rating of a post when the rating has been made like mentioned by the @Guy L 有一列计算和存储帖子平均评分的列,例如@Guy L提到的那样

  2. Implementing a Cache with TTL(Time To Live) 用TTL实现生存时间

example: 例:

public function getAverageRating() {
     $post_id = 'post' . $this->id;
     if(Cache::has($post_id))
         return Cache::get($post_id);
     $rating = //fetch rating from DB
     Cache::set($post_id, $rating, 120); //ratings will be in the cahce for 120secs
     return $rating
}

Hope it helps. 希望能帮助到你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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