# 干货场景 - 热门评论排序
前言 : sql 语言为 Mysql
计算权重? 代码太多? 通通不需要! 仅需要这一句代码, 便能做到接近企业级热门评论排序
以下进行展开
点赞与时间的平衡
在设计推荐算法时,我们面临一个核心问题:如何平衡`新评论与老评论`的优先级?只看点赞数,老评论因时间积累占优;只看发布时间,新评论可能忽略质量; 为此,我们引入一个平衡公式,既体现点赞量,又让得分随时间衰减;
类似于
必要列 : “score”
介绍: 算力分, 用作排序, 通过公式计算出
实际也可以通过公式在查询中进行排序, 为什么要设计这一个列?
目的是为了存储计算结果,减少重复计算,提高系统效率; 通过预先计算并保存得分, 可以在排序或推荐时直接使用,而无需每次实时计算公式;
字段名称 | 数据库字段名 | 描述 | 备注 |
---|---|---|---|
主键(PK) | id | 主键 | |
评论评论 | content | 评论评论 | |
… | … | … | … |
算力分 | score (保留两位小数) | sql动态计算的算力分 | 用于做热门排序 |
发布者(FK) | u_id | 发布的用户ID | |
评论作品(FK) | iss_id | 评论的作品ID |
公式概览
我们采用以下公式计算得分(score
), 并在用户点赞时调用该公式实时计算得分
SET score = like_num / POW(TIMESTAMPDIFF(SECOND, create_time, NOW()) + 1, 0.5);
这个公式看起来复杂,但本质上是一个很简单的逻辑:得分 = 点赞数 / 时间的平方根
公式作用 :
- 点赞数越多,得分越高
- 时间越长,得分会逐渐减小
- 新评论由于时间短,在同等点赞数下会更有优势
逐步剖析公式
-
点赞数(
like_num
)
like_num
是评论的点赞数,直接决定了得分的上限;-
点赞多的评论,得分自然会更高
-
点赞少的评论,得分会偏低
-
这是公式的基础:点赞越多越受欢迎
-
时间差(
TIMESTAMPDIFF(SECOND, create_time, NOW())
)
TIMESTAMPDIFF
计算评论的存在时间:-
SECOND
表示单位是秒 -
create_time
是评论的创建时间 -
NOW()
是当前时间
-
计算的结果是评论从发布到现在的总秒数,时间越长,得分会因为时间的衰减而减少
-
避免零值(
+ 1
)
为避免刚发布时时间差为 0 导致计算错误,我们在时间差上加 1; 这是一个小技巧:-
如果时间差是 0,
+ 1
确保公式能正常计算 -
对于很短的时间差,加 1 对得分影响不大,并且这是公共的,也很公平
-
为什么避免零值?
score = like_num / POW(TIMESTAMPDIFF(SECOND, create_time, NOW()) + 1);
如果评论刚发布,创建时间
create_time
和 现在时间NOW()
是相同的,TIMESTAMPDIFF(SECOND, create_time, NOW())
就会是 0。
如果没有+ 1
,计算结果会是:score = like_num / POW(0)
而 POW(0) 是 0,0 除 0 会报错。
score = 0 / POW(1) = 0
所以
+ 1
后,分母就成了 1,计算就成了 0 除 1, 从而避免了错误计算。总结:
+ 1
是为了防止时间差为零时公式报错。第一次点赞时sql还没被执行, 所以点赞量还没变化值为0, 0除以0 就会报错
-
-
时间平方根(
POW(..., 0.5)
)
POW(..., 0.5)
对时间差 开平方- 随着时间变长,得分衰减的速度会逐渐变慢
- 这意味着,老评论虽然得分会下降,但衰减速度不会太快,可以保留一定的竞争力
整体逻辑
综合起来,公式的核心逻辑是:
- 点赞数决定评论的得分基础
- 时间越长,得分逐渐减少,但通过平方根函数,让得分的下降幅度变得平滑
示例分析
三个评论的具体得分计算示例 :
评论数据
评论 | 点赞数 | 发布时间 | 当前时间 | 时间差(秒) |
---|---|---|---|---|
A | 100 | 2024-12-12 08:00 | 2024-12-12 10:00 | 7200 (两个钟) |
B | 200 | 2024-12-12 09:00 | 2024-12-12 10:00 | 3600 (一个钟) |
C | 50 | 2024-12-12 09:30 | 2024-12-12 10:00 | 1800 (半个钟) |
逐步计算
-
A
-
点赞数:
100
-
时间差:
7200
-
时间平方根:
POW(7200 + 1) ≈ 84.85
-
得分:
100 / 84.85 ≈ 1.18
-
-
B
-
点赞数:
200
-
时间差:
3600
-
时间平方根:
POW(3600 + 1) ≈ 60.01
-
得分:
200 / 60.01 ≈ 3.33
-
-
C
-
点赞数:
50
-
时间差:
1800
-
时间平方根:
POW(1800 + 1) ≈ 42.44
-
得分:
50 / 42.44 ≈ 1.18
(手打约等号好累… 货这么干不给个关注么 (⁄ ⁄>⁄ ▽ ⁄<⁄ ⁄)
-
总结对比
评论 | 点赞数 | 时间差(秒) | 得分 |
---|---|---|---|
A | 100 | 7200 | 1.18 |
B | 200 | 3600 | 3.33 |
C | 50 | 1800 | 1.18 |
观察:
-
点赞数的重要性:
评论 B 的点赞数最多,因此得分最高,即使它的时间差较大 -
时间的影响:
评论 A 和评论 C 得分相同,尽管 A 的点赞数更多,但由于存在时间更长(7200 秒 vs. 1800 秒),导致得分被时间衰减 -
时间衰减的平滑性:
时间通过平方根衰减,不会让得分下降过快; 例如,评论 A 虽然时间更长,但得分的减少是逐步的,而不是骤降
为什么用这个公式?
这个公式在很多评论推荐系统中被广泛使用,原因在于它能够平衡以下需求:
-
公平性:
新评论(时间短)在得分计算中具有一定优势,避免被老评论垄断推荐位 -
质量性:
得分的核心仍然是点赞数,点赞数多的评论更容易得到推荐 -
时间衰减的合理性:
时间的影响通过平方根进行平滑衰减,让老评论虽然得分逐渐减少,但仍保留竞争力
总结
该公式将点赞数和时间有效结合,既保证热门评论 (被点赞多) 的推荐,又让新评论有曝光机会;
拓展:加入回复量作为因子
除了点赞数,回复量 也是衡量内容质量的关键。像回复的互动性往往比单纯的点赞更能反映内容的质量/影响。因此,可以在计算得分时,将回复量纳入公式,进一步优化推荐逻辑。
新公式
在原公式的基础上,将 回复量(replies) 加入得分计算,可以这样设计:
SET score = (like_num + α * replies) / POW(TIMESTAMPDIFF(SECOND, create_time, NOW()) + 1, 0.5);
like_num
:点赞数,依然是核心因子;replies
:回复量,用来反映内容的互动程度;α
(权重因子):设定回复量的影响权重,比如设定为2
,表示每条回复相当于 2 次点赞;POW(..., 0.5)
:时间衰减,与原公式相同,平衡时间影响。
使用场景
高互动内容的优先推荐
在一些平台, 用户更关注高互动的内容。通过加入回复量,高互动内容得分会更高,比如一条有 10 个点赞、50 条回复的帖子,其得分可能高于一条只有 100 个点赞但无人回复的内容。
示例:
-
帖子 A:10 个点赞 + 50 条回复;
-
帖子 B:100 个点赞 + 0 条回复;
假设 α = 2
则:
- A 的得分因点赞和回复为
10 + 2 * 50 = 110
; - B 的得分因点赞为
100
; - A 得分 > B,优先推荐 A。
- A 的得分因点赞和回复为
平衡点赞和回复
像bilibili,点赞通常快但评论少,可以调低 α
的值,比如设为 1
或更低,减小回复量的影响,确保内容得分主要由点赞数决定,而回复量仅作为辅助因子。
A:10 个点赞 + 50 条回复;
-
帖子 B:100 个点赞 + 0 条回复;
假设 α = 2
则:
- A 的得分因点赞和回复为
10 + 2 * 50 = 110
; - B 的得分因点赞为
100
; - A 得分 > B,优先推荐 A。
- A 的得分因点赞和回复为
平衡点赞和回复
像bilibili,点赞通常快但评论少,可以调低 α
的值,比如设为 1
或更低,减小回复量的影响,确保内容得分主要由点赞数决定,而回复量仅作为辅助因子。
end
如果这篇文章帮到你, 帮忙点个关注呗, 不想那那那点赞或收藏也行丫 ~ (。•ᴗ-)✧
'(இ﹏இ`。)