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

Laravel Eloquent:能否用单查询实现指定顺序关联视频获取?

单查询实现按关联类型优先级获取视频

要实现按「关联Cars的视频优先,其次是Bikes,最后是Trucks」的顺序返回最多6条视频,且仅用单次查询,可以通过给视频标记优先级权重的方式实现,核心思路是用CASE语句结合关联存在判断排序,同时确保去重。

实现代码

protected function related(Video $video): Collection
{
    $nVideos = 6;
    
    // 获取当前视频关联的各模型ID集合
    $carIds = $video->cars->pluck('id')->toArray();
    $bikeIds = $video->bikes->pluck('id')->toArray();
    $truckIds = $video->trucks->pluck('id')->toArray();

    // 获取多对多关联的中间表名(适配自定义表名场景)
    $carPivotTable = (new Video)->cars()->getTable();
    $bikePivotTable = (new Video)->bikes()->getTable();
    $truckPivotTable = (new Video)->trucks()->getTable();

    return Video::whereNot('id', $video->id)
        // 筛选关联至少一种目标类型的视频
        ->where(function ($query) use ($carIds, $bikeIds, $truckIds) {
            $query->whereHas('cars', fn($q) => $q->whereIn('id', $carIds))
                  ->orWhereHas('bikes', fn($q) => $q->whereIn('id', $bikeIds))
                  ->orWhereHas('trucks', fn($q) => $q->whereIn('id', $truckIds));
        })
        // 按关联类型优先级排序:Cars(1) > Bikes(2) > Trucks(3)
        ->orderByRaw("
            CASE
                WHEN EXISTS (SELECT 1 FROM {$carPivotTable} WHERE video_id = videos.id AND car_id IN (" . implode(',', $carIds) . ")) THEN 1
                WHEN EXISTS (SELECT 1 FROM {$bikePivotTable} WHERE video_id = videos.id AND bike_id IN (" . implode(',', $bikeIds) . ")) THEN 2
                WHEN EXISTS (SELECT 1 FROM {$truckPivotTable} WHERE video_id = videos.id AND truck_id IN (" . implode(',', $truckIds) . ")) THEN 3
                ELSE 4
            END
        ")
        // 避免同一视频因关联多类型重复出现
        ->distinct()
        ->take($nVideos)
        ->get();
}

关键说明

  1. 优先级排序逻辑:通过CASE语句和EXISTS子查询,直接在数据库层面判断视频是否关联对应类型,给不同类型分配排序权重,确保关联Cars的视频排在最前。
  2. 去重处理:使用distinct()保证同一视频即使关联多个类型,也只会按最高优先级返回一次。
  3. 适配自定义中间表:通过模型关联方法获取中间表名,避免硬编码表名导致的兼容性问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 10:53:17