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

Laravel 10中使用inRandomOrder如何避免获取重复记录?

解决Laravel 10中inRandomOrder偶尔出现重复记录的问题

先明确两种常见场景及对应解决方案:

场景1:数据库中存在内容重复的Question记录

如果Question表本身存有重复内容的记录(比如同一问题多次录入),inRandomOrder()随机抽取时自然会抽到重复内容,可通过去重后再随机排序解决:

方法1:用distinct()按字段去重

// 按指定字段(如title)去重,确保返回的记录内容唯一
$questions = Question::distinct('title')
    ->inRandomOrder()
    ->limit(50)
    ->get();

方法2:用groupBy()分组去重

// 按唯一标识字段分组,过滤重复内容
$questions = Question::select('*')
    ->groupBy('title') // 替换为你用来判断重复的字段(如content、uuid等)
    ->inRandomOrder()
    ->limit(50)
    ->get();

注意:使用MySQL时,需确保sql_mode未开启ONLY_FULL_GROUP_BY,或select的字段均包含在groupBy中,否则会触发SQL错误。

场景2:数据库无重复记录,但仍出现重复返回

若Question表主键(id)唯一,但偶尔出现同一id的记录被重复返回,可尝试以下方案:

方法1:用随机偏移量替代inRandomOrder()

适合数据量较小的场景,通过计算随机偏移量抽取记录:

$total = Question::count();
// 确保偏移量不超出数据范围
$offset = $total > 50 ? rand(0, $total - 50) : 0;
$questions = Question::skip($offset)->take(50)->get();

方法2:排除已抽取的记录(多请求防重复场景)

如果需要在一段时间内避免给同一用户返回重复记录,可借助Redis缓存已抽取的id:

// 从Redis获取已抽取的记录id
$excludeIds = Redis::get('selected_question_ids') ?: [];
// 排除已抽取的id,随机取新记录
$questions = Question::whereNotIn('id', $excludeIds)
    ->inRandomOrder()
    ->limit(50)
    ->get();

// 更新缓存,新增本次抽取的id,设置过期时间(示例为1小时)
$newExcludeIds = array_merge($excludeIds, $questions->pluck('id')->toArray());
Redis::set('selected_question_ids', $newExcludeIds, 3600);

方法3:排查关联查询导致的重复

如果查询包含关联关系(如with()),可能因关联数据产生重复行,可通过distinct()确保主键唯一:

$questions = Question::with('categories') // 假设存在关联关系
    ->distinct()
    ->inRandomOrder()
    ->limit(50)
    ->get();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 21:57:50