简体   繁体   English

帖子的多重评级系统(如爱,明星)

[英]Multiple rating system for posts (like, love, star)

I need to develop a voting system for posts. 我需要为帖子开发一个投票系统。 Every user can like a post by clicking on thumb icon and love a post by clicking on hearth icon, in the future maybe I have a star system as alternatives. 每个用户都可以一个帖子点击拇指图标,点击图标炉爱岗位,今后也许我有一个恒星系统的替代品。

I'm looking for better solutions to implement this system, for now, I've thought this two way: 我正在寻找更好的解决方案来实现这个系统,现在,我想到了这两种方式:

  • 1) one table for each voting system 1)每个投票系统一个表
tbl like

id
post_id
user_id
value // value even 1

tbl love

id
post_id
user_id
value // value even 1

tbl star

id
post_id
user_id
value // value between 1 and 5

  • 2) one single table for all voting system 2)所有投票系统的单一表格
tbl rate

id
post_id
user_id
type // 'like' or 'love' or 'star'
value // value between 1 and 5

Which is the better solution? 哪个更好的解决方案?

And other thing, when I query multiple posts isn't good SELECT and sum (or avg) every vote, maybe is good to save in posts table the sum (or avg) of current like/love/star to speed up the query, and then update the posts on every new like/love/star? 和其他的事情,当我查询多个帖子不好SELECT和sum(或平均)每次投票, 也许是很好的保存在帖子表中当前喜欢/ love / star的总和(或平均)来加快查询,然后更新每个新/喜欢/爱/明星的帖子?

The last thing, to let the user see if he has already voted some posts , it's a good solution a query like this? 最后一件事, 让用户看看他是否已经投了一些帖子 ,这是一个很好的解决方案吗? SELECT post_id FROM rate WHERE user_id = <MYUSERID> AND post_id IN (<ARRAYOFPOSTS>) and then compare the retrieved post_id with the post_id of the main query? SELECT post_id FROM rate WHERE user_id = <MYUSERID> AND post_id IN (<ARRAYOFPOSTS>)然后将检索到的post_id与主查询的post_id进行比较?

Thank you! 谢谢!

As Eric mentioned, having multiple tables is not usually a very good idea performance wise. 正如埃里克所说,拥有多个表通常不是一个非常好的表现。

For each table MySQL is required to maintain internal data structures, a data dictionary, file descriptions and so on... 对于每个表,MySQL需要维护内部数据结构,数据字典,文件描述等...

Go with solution 2 . 使用解决方案2

This would be the best solution in terms of both performance and scalability of your application for the future. 就未来应用程序的性能和可伸缩性而言,这将是最佳解决方案。 Instead of having to support a completely new table when expanding votes, you simply need to allow your application to show a new type of vote in the frontend. 您只需要允许您的应用程序在前端显示新类型的投票,而不必在扩展投票时支持全新的表格。

When fetching statistics for the given article, you could as you say, save this every time a user votes to not have to fetch the full count each time, however the performance gain won't really be noticeable at all, instead make some good indexes to speed things up once it's needed. 在获取给定文章的统计信息时,您可以按照说明,每次用户投票时都不需要每次都获取完整计数,但是性能增益根本不会明显,而是制作一些好的索引一旦需要,加快速度。

If you wish to show the user if he has voted for a given post I would recommend simply checking the rate table you describe in solution 2. If you wish to limit amount of queries from your application you could as you say fetch all posts on the page, then query on those. 如果您希望向用户显示他是否已投票给某个帖子,我建议您只需查看您在解决方案2中描述的rate表。如果您希望限制应用程序中的查询数量,您可以按照说明获取所有帖子页面,然后查询那些。 However the performance gain here is also minimal I would say. 然而,我认为这里的性能提升也很小。

Some good indexes would solve most of your performance concerns for the foreseeable future. 在可预见的未来,一些好的指标可以解决您的大多数性能问题。 Usually the only time you'll need to split the data is when the whole database can't handle all the traffic. 通常,您需要分割数据的唯一时间是整个数据库无法处理所有流量。 This article from the Airbnb team gives an idea of when that might be the case. 来自Airbnb团队的这篇文章让我们知道何时可能出现这种情况。

A small tip would be to not overthink the application. 一个小小的提示是不要过度思考应用程序。 Usually it's better to start out small and do things the easy way. 通常最好从小开始,以简单的方式做事。 This way you won't introduce more issues than necessary. 这样您就不会引入超出必要的问题。 Once the application then grows, the issues will come naturally and you'll solve them as they come. 一旦应用程序增长,问题就会自然而然,你会在它们到来时解决它们。

Your second approach is a "simple" implementation of the Entity–attribute–value model . 您的第二种方法是实体属性值模型的“简单”实现。 But there is nothing really simple about EAV in practice. 但实际上EAV没有什么比这更简单的了。 Usually EAV is used for user defined attributes. 通常EAV用于用户定义的属性。 This is not the case here. 这不是这种情况。 And I don't see any other good reason in your post. 我在你的帖子中没有看到任何其他正当理由。 "I don't want to create a new table or column every time I implement a new feature" is a bad one. “每次实现新功能时,我都不想创建新的表或列”是一个糟糕的功能。

There is also no general rule, if one table is better than multiple tables. 如果一个表优于多个表,则也没有一般规则。 The pure number of tables says nothing about the quality of a database design. 纯数量的表格没有说明数据库设计的质量。 You need to analyse the requirements, the entities and relations. 您需要分析需求,实体和关系。 And that brings me to the next point.. 这让我想到了下一点......

Your first two tables are not even entities. 您的前两个表甚至不是实体。 "User likes a post" and "User loves a post" are pure relations. “用户喜欢帖子”和“用户喜欢帖子”是纯粹的关系。 The value column makes no sense, since it can only contain 1 , and thus holds no information. value列没有意义,因为它只能包含1 ,因此不包含任何信息。 So your tables should actually look like: 所以你的表应该看起来像:

user_post_likes (
    user_id (FK, PK)
    post_id (FK, PK)
)

user_post_loves (
    user_id (FK, PK)
    post_id (FK, PK)
)

user_post_ratings (
    user_id (FK, PK)
    post_id (FK, PK)
    rating [1-5]
)

The first two tables are clearly different from the third one. 前两个表与第三个表明显不同。 Merging them into one table would be a strange idea. 将它们合并到一个表中将是一个奇怪的想法。 And the first two tables should neither be merged, if they are actually two different relations, even when they have the same signature. 并且前两个表既不应该合并,如果它们实际上是两个不同的关系,即使它们具有相同的签名。 (It would be similar to merging two functions sum(x,y) and diff(x,y) into calc(operator, x, y) .) (这类似于将两个函数sum(x,y)diff(x,y)合并为calc(operator, x, y) 。)

The next point depends on the requirements. 下一点取决于要求。 I doubt that you ever want a post to be liked and loved at the same time from the same user. 我怀疑你是否曾想要同一个用户同时喜欢和喜爱的帖子。 If likes and loves are exclusive, then it should be one entity. 如果喜欢和爱是独家的,那么它应该是一个实体。 The table could be something like 表可能是这样的

user_post_flags (
    user_id (FK, PK)
    post_id (FK, PK)
    flag [like|love]
)

(Sorry - finding good identifiers is a hard task ;-)) (对不起 - 找到好的标识符是一项艰巨的任务;-))

You can code 'like' and 'love' with 1 and 2 (or whatever you want). 你可以用12 (或任何你想要的)代码'喜欢'和'爱'。 And while it now looks like the ratings table, they are still two different things, and should have separate tables. 虽然它现在看起来像评级表,但它们仍然是两个不同的东西,应该有单独的表。

Regarding performance: This highly depends on the task/requirement. 关于性能:这在很大程度上取决于任务/要求。 But I never heard of EAV model being chosen for performance reasons. 但我从未听说过因性能原因而选择的EAV模型。 (Except of myself, but that doesn't count :-).) (除了我自己,但不计算:-)。)

From your original question 从你原来的问题

…in the future maybe I have a star system as alternatives (sic) ......将来也许我有一个明星系统作为替代品(原文如此)

Why are you attempting to solve a problem you don't have yet? 你为什么试图解决你还没有的问题? Presumably you don't want to run both a reaction system ( like|love ) and a rating system ( star ) side by side 大概你不想同时运行反应系统( 如|爱 )和评级系统( 星级

I'd also question the value of what a love reaction gives you, and the user, over and above a like . 我还怀疑一个什么样的爱情反应给你,用户,之上一的值。 I know facebook does it, but they have a huge amount of data and another 4 reactions ( sad|angry|wow|haha ) 我知道facebook做到了,但他们有大量的数据和另外4个反应( 伤心|生气|哇|哈哈

Honestly, I'd forget about everything except the likes and just start with (from @PaulSpiegel's answer) 老实说,我会忘记除了喜欢之外的所有事情,并且开始时(来自@ PaulSpiegel的回答)

user_post_like (
  user_id (FK, PK)
  post_id (FK, PK)
)

Then move on! 继续前进!

You can always come back and add to this system, change it, migrate the data if the system requires it 您可以随时返回并添加到此系统,更改它,在系统需要时迁移数据

Don't give yourself decision fatigue trying to build a super generic system that solves everything 不要试图建立一个解决所有问题的超级通用系统,让自己决定疲劳

Option 3: 选项3:

user_id ... NOT NULL,
post_id ... NOT NULL,
like TINYINT NULL,   -- NULL means no action on LIKEing
love TINYINT NULL,
rate TINYINT NULL,
PRIMARY KEY(user_id, post_id),
INDEX(post_id, user_id)

Or combine like and love in some way. 或者以某种方式结合likelove

But the real test of how to design the schema comes when you write the queries to set/change/query/summarize the values. 但是,当您编写查询以设置/更改/查询/汇总值时,会对如何设计模式进行真正的测试。

My suggestion is kind of method 2. 我的建议是方法2。

You can combine rate_type and rate_value in a table. 您可以在表中组合rate_type和rate_value。 Create all posibilities in for rate, love and star (1 to 5) This is an advantage for future cause, it has less data in tbl rate when record count increased. 为速率,爱情和明星创建所有可能性(1到5)这是未来原因的优势,当记录数增加时,它在tbl速率中的数据较少。

I don' t offer 'count based' tables. 我没有提供'基于计数'的表格。 That kind of tables has lock posibilities in high traffic. 这种表在高流量时具有锁定能力。

Disadvantage for this combined rate_type style is, it will be a little harder to manage in code. 这种组合的rate_type风格的缺点是,在代码中管理起来会有点困难。

My proposal; 我的建议;

tbl_rate_type

    id tinyint
    name nvarchar(5)  // if you want


tbl_rate_type_kind

    id tinyint,
    rate_type_id tinyint,
    rate_value tinyint,
    name nvarchar(5),   // if you want
    image_id smallint   // Advantage for viewing specific images simply


tbl rate

   id bigint
   post_id bigint 
   user_id int
   rate_type_kind_id  tinyint   // numeric value is better for indexing.

I'm looking for a solutions that match all the suggestions that I've received. 我正在寻找符合我收到的所有建议的解决方案。 I'll try to develop one single column with leverage of the composite index . 我将尝试利用复合索引开发一个单独的列 This is the solutions that I want to try: 这是我想要尝试的解决方案:

Table: rating

----------
user_id : bigint
post_id : bigint
rate_type : varchar (like/love/star)
rate : tinyint (0-5) // default 1 (for like/love)
----------

key: INDEX(user_id, post_id)
no PRIMARY // I don't care about duplicate key that may exist (same post like/love)

In this test table I've added 1000 rows and tried to query: 在此测试表中,我添加了1000行并尝试查询:

SELECT * FROM rating WHERE user_id = 21; //EXPLAIN KEY:rate ROWS:4

SELECT * FROM rating WHERE user_id = 21 AND rate_type = 'like'; //EXPLAIN KEY:rate ROWS:4

SELECT * FROM rating WHERE user_id = 21 AND rate_type = 'like'; //EXPLAIN KEY:rate ROWS:4

SELECT * FROM rating WHERE user_id = 21 AND post_id = 179 AND rate_type = 'like'; //EXPLAIN KEY:rate ROWS:1

What do you think? 你怎么看? Is this a good solutions? 这是一个好的解决方案吗? Use a simple INDEX and not a PRIMARY may have consequences? 使用简单的INDEX而不是PRIMARY可能会产生什么后果? I can't use PRIMARY because may happen that I have this three rows: 我不能使用PRIMARY,因为可能会发生我有这三行:

 user_id: 21 - post_id: 173 - rate_type: 'like'
 user_id: 21 - post_id: 173 - rate_type: 'love'
 user_id: 21 - post_id: 173 - rate_type: 'star'

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

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