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

Laravel统计每篇文章评论的去重用户数最优实现方法

需求说明
  • 业务涉及Post(文章)、comments(评论表)、用户三类数据:每篇文章关联多条评论,每条评论归属于单个用户。
  • 目标:查询文章列表时,同步统计每篇文章下发表过评论的独立去重用户总数,同一用户对同一篇文章发表多条评论仅计数1次。
  • 当前实现存在性能问题,代码如下:
$posts = Post::query()
               ->where('category',$request->input('category'))
               // other conditions
               ->get();

$numberOfUsers=[];
forech($posts as $post){
    $numberOfUsers[$post->id] = $post->comments()->groupBy('user')->count();
}
  • 此前尝试使用belongsToMany、hasMany、hasManyThrough等关联方法搭配groupBy查询,仅能得到评论总条数,无法得到去重用户数,需要正确的高效实现方案。

高效实现方案

方案1:模型定义去重关联+预加载统计(推荐)

在Post模型中定义评论用户的多对多关联,自动完成用户去重:

// Post模型内添加关联方法
public function commentUsers()
{
    return $this->belongsToMany(User::class, 'comments', 'post_id', 'user_id')
        ->distinct();
}

查询时使用withCount批量预加载统计值,全程仅执行2条SQL,完全避免N+1查询问题:

$posts = Post::query()
    ->where('category', $request->input('category'))
    // 其他筛选条件
    ->withCount('commentUsers')
    ->get();

统计结果会自动挂载到每个文章模型的comment_users_count属性上,直接调用即可:

foreach ($posts as $post) {
    // $post->comment_users_count 就是当前文章的去重评论用户数
}

方案2:闭包统计(无需新增模型关联)

如果不想新增模型关联方法,可以直接在withCount中传入闭包,手动写去重统计逻辑:

$posts = Post::query()
    ->where('category', $request->input('category'))
    ->withCount([
        'comments' => function ($q) {
            $q->select(\DB::raw('count(distinct user_id)'));
        }
    ])
    ->get();

统计结果挂载在comments_count属性上,直接访问即可。

原循环查询写法属于典型N+1问题:每遍历一篇文章就执行1次count查询,文章总量越大查询次数越多,性能会随数据量增长线性下降。上述两种方案均为批量查询,性能差距可达数十到数百倍。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 19:09:22