Laravel中如何按关联Video总时长限制查询用户的随机视频集合
需求可实现,以下是适配不同场景的具体实现方案
方案1:中小数据量场景(逻辑简单易维护)
- 实现逻辑:预加载用户关联视频后,对每个用户的视频做随机排序,累加时长直到落入目标区间,自动过滤无法凑出符合要求时长的用户
- 代码示例:
// 预加载用户的有效视频,可自行补充视频的状态过滤条件 $users = User::with(['videos' => function($query) { $query->where('status', 'published'); }])->get()->filter(function($user) { // 随机打乱用户视频顺序 $shuffledVideos = $user->videos->shuffle(); $total = 0; $result = collect(); foreach ($shuffledVideos as $video) { // 累加后不超出上限就加入结果集 if ($total + $video->length <= 12000) { $total += $video->length; $result->push($video); } // 达到下限就提前终止循环 if ($total >= 10000) break; } // 仅保留符合时长要求的用户,把选中的视频挂载到用户对象上 if ($total >= 10000 && $total <= 12000) { $user->selected_videos = $result; return true; } return false; });
方案2:大数据量场景(降低内存占用)
- 实现逻辑:先在数据库层过滤掉所有视频总时长不足10000秒的用户,再对剩余用户执行随机选视频逻辑,避免无效数据加载
- 预筛选用户代码:
// 先过滤掉视频总时长不足10000秒、根本不可能符合要求的用户 $validUsers = User::whereHas('videos', function($query) { $query->select(DB::raw('sum(length) as total_length')) ->groupBy('user_id') ->having('total_length', '>=', 10000); })->with('videos')->get(); // 后续对$validUsers执行方案1中的随机选视频逻辑即可
优化提示
- 单条视频最长为8000秒的前提下,最多3条视频就能凑够时长下限,可在关联查询视频时加
inRandomOrder()->take(20)限制加载数量,进一步降低内存消耗 - 如果需要固定随机结果,可给
shuffle()传入固定seed值 - 可提前过滤掉时长>12000秒的异常视频,避免单条视频直接超出上限
内容的提问来源于stack exchange,提问作者Martin Szotkovski
相关产品推荐
相关产品推荐

