因此,通过研究我发现,设计喜欢的帖子的最佳方法是拥有一个类似以下的数据库。假设像Reddit一样,帖子可以被投票,被投票或完全不投票。
该数据库将具有三列,[用户名,帖子,喜欢的]。
喜欢是某种布尔值,1表示喜欢,0表示不喜欢。
然后要查找类似金额的帖子,例如,我会做SELECT COUNT(*) FROM likes WHERE post=12341 AND liked=1
,然后对liked=0
做同样的事情(不喜欢),然后在附加服务器端进行辩论,并提出争议百分比。
因此,我首先要担心的是,找出用户是否喜欢帖子的合适方法是什么?我会尝试选择liked
布尔值,还是检索或捕获错误。还是我先检查记录是否存在,然后再进行选择以找出该值?如果我想检查用户是否一次喜欢多个帖子怎么办?
第二,该表不需要主键吗?因为没有行将具有相同的帖子和用户名,所以我应该使用复合主键吗?
答案 0 :(得分:0)
给出建议的3列表格和建议的选择,请确保具有
PRIMARY KEY(username, post) -- helps with "did user like a post"
INDEX(post_id, liked) -- for that COUNT
在检查用户是否喜欢帖子时,请执行LEFT JOIN
,以便获得以下三项之一:1 =喜欢,0 =不喜欢,或者NULL =不投票。或者,您可以使用EXISTS( SELECT .. )
表需要PK。
答案 1 :(得分:0)
我同意里克·詹姆斯(Rick James)的观点,likes
表应该通过({username
,post
)对来唯一索引。
另外,我建议您保留一点冗余,并将like_counter
保留在posts
表中。这将使您大大减少常规查询的负担。
在成功添加完喜欢/不喜欢记录后,立即增加或减少计数器。
总而言之,
答案 2 :(得分:0)
我最初的想法是因为问题在于布尔类型不够丰富,无法表达对帖子的可能反应。因此,您需要一个枚举,其状态可能为Liked
,Disliked
,而不是布尔值,并且第三个状态和默认状态为Un-reacted
。
但是现在看来,您也可以取消布尔值,因为您不需要记录Un-reacted
状态。缺乏反应意味着您不会在表中添加条目。
找出用户是否喜欢帖子的合适方法是什么?
SELECT Liked
FROM Likes
WHERE Likes.PostId == 1234
AND Likes.UserName == "UniqueUserName";
如果用户未与该帖子互动,将不会有任何结果。否则,如果喜欢,则1
,如果不喜欢,则0
。
如果我要检查用户是否一次喜欢多个帖子怎么办?
为此,您还需要存储一个时间戳。然后,您可以使用该时间戳记,看看它是否在短时间内有多个喜欢的帖子。
您可以采用k均值聚类来确定是否有任何“喜欢”集群。完整的说明太大了,无法在此处添加。
此表是否不需要主键?
当然可以。但是Like
是弱实体,具体取决于Post
。因此,它将需要Post
的PK,即字段post
(我认为)。结合username
我们将拥有PK,因为(post
,username
)对于用户的反应而言是唯一的。
答案 3 :(得分:0)
为了提高性能,您将需要更改数据库计划:
字段:
Liked
应该是布尔值,您是对的。您可以在代码中将其转换为-1 / + 1。您将把数字总计缓存在其他位置。Username
应该是UserID
。您只需要此表中的数值来提高速度。Post
应该为PostID
。您还需要数字主键,因为它们更易于搜索和执行子选择。
并在(Username
,Post
)上创建唯一索引,因为该表主要是为提高速度而建立的索引。
那么用户对帖子投票了吗?
select id
from user_likes_post
where userID = 123 and postID = 456;
用户喜欢帖子吗?
select id
from user_likes_post
where userID = 123 and postID = 456 and liked = true;
您不必担心错误,您可以获取结果,也可以不获取结果,因此您最好直接获得所需的值:
select liked from user_liked_post where userID=123 and postID=456
获取他们喜欢的所有帖子:
select postID
from user_likes_post
where userID = 123 and liked = true;
PostID
TotalLikes
TotalDislikes
Score
通过对第一个表进行计算,第二个表将每 n 分钟转储并刷新。第二张表是您缓存的总得分,您将为访问该帖子的所有用户实际加载该总得分。调整此重复转储和填充计划的频率,但是您认为合适。对于业余爱好或学生项目,每30秒或2分钟进行一次;较大的站点,每10或15分钟。对于更大的站点,例如reddit,您希望使架构更复杂,以使站点中较忙的部分可以更快地刷新。
// this is not exact code, just an outline
totalLikes =
select count(*)
from user_likes_post
where postID=123 and liked=true
totalDislikes =
select count(*)
from user_likes_post
where postID=123 and liked=false
totalVotes = totalLikes + totalDislikes
score = totalLikes / totalVotes;
(您可以通过涉及用户的localStorage
-客户端Javascript来模拟更新,该Javascript显示用户投票过的帖子的上下颠簸。)