You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何计算Laravel中Server(等价Post)的评分并生成Top10榜单

解决方案:Server评分计算与Top10榜单实现

1. 修正模型关联错误

你的ServerUserLike模型里的server()关联写法有误,一条点赞记录属于单个Server,应该用belongsTo而非hasMany:

public function server()
{
    return $this->belongsTo(Server::class);
}

2. 批量统计单Server点赞数

无需单独查询单Server和总点赞数,直接用分组查询一次性统计所有Server的点赞数据,效率更高:

// 统计每个Server的点赞数
$serverLikeStats = DB::table('server_user_likes')
    ->select('server_id', DB::raw('count(*) as like_count'))
    ->groupBy('server_id')
    ->get();

3. 选择适合动态场景的评分算法

由于数据动态增长,普通的点赞数排序会导致新Server因少量点赞就占据高位,推荐两种适合的算法:

算法一:贝叶斯平均评分

平衡全局平均点赞数与单Server点赞数,避免极端情况,公式为:
$score = \frac{C \times m + n}{C + n}$

  • $C$:调整系数(建议取全局平均点赞数或Server点赞数的中位数)
  • $m$:所有Server的平均点赞数
  • $n$:当前Server的点赞数

Laravel实现(直接在数据库层面计算):

// 计算全局基础数据
$totalServers = Server::count();
$totalLikes = DB::table('server_user_likes')->count();
$averageLikes = $totalServers > 0 ? $totalLikes / $totalServers : 0;
// 取全局平均作为调整系数C
$C = $averageLikes;

// 计算Top10 Server
$topServers = Server::leftJoin('server_user_likes', 'servers.id', '=', 'server_user_likes.server_id')
    ->select([
        'servers.*',
        DB::raw('COUNT(server_user_likes.id) AS like_count'),
        DB::raw('(' . $C . ' * ' . $averageLikes . ' + COUNT(server_user_likes.id)) / (' . $C . ' + COUNT(server_user_likes.id)) AS score')
    ])
    ->groupBy('servers.id')
    ->orderBy('score', 'DESC')
    ->limit(10)
    ->get();

算法二:威尔逊得分

更严谨的统计模型,基于置信区间计算得分,适合点赞/无点赞的二项分布场景,能有效过滤样本量小的Server:

// 定义威尔逊得分计算函数
function calculateWilsonScore(int $likeCount): float
{
    $z = 1.96; // 95%置信区间对应的Z值
    $n = $likeCount;
    
    if ($n === 0) return 0;
    
    $p = 1; // 仅统计点赞,点赞率为1
    $numerator = $p + ($z**2)/(2*$n) - $z*sqrt(($p*(1-$p))/$n + ($z**2)/(4*$n**2));
    $denominator = 1 + ($z**2)/$n;
    
    return $numerator / $denominator;
}

// 获取所有Server的点赞数并计算得分,再取Top10
$serverLikes = DB::table('server_user_likes')
    ->select('server_id', DB::raw('count(*) as like_count'))
    ->groupBy('server_id')
    ->get()
    ->map(function ($item) {
        $item->score = calculateWilsonScore($item->like_count);
        return $item;
    })
    ->sortByDesc('score')
    ->take(10)
    // 关联Server详情(可选)
    ->each(function ($item) {
        $item->server = Server::find($item->server_id);
    });

4. 性能优化建议

针对动态增长的海量数据,建议:

  • 缓存榜单:用Redis缓存Top10结果,每隔固定时间(如10分钟)刷新一次,避免频繁计算
  • 数据库索引:确保server_user_likes表的server_id索引生效(你已添加,无需改动)
  • 异步计算:如果数据量极大,可将评分计算逻辑放入队列异步执行,不阻塞请求

内容的提问来源于stack exchange,提问作者CARSAR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 23:46:01