题 Laravel - Eloquent或Fluent随机排


如何在Laravel框架中使用Eloquent或Fluent选择随机行?

我知道通过使用SQL,您可以通过RAND()进行排序。但是,我想获得随机行  在初始查询之前计算记录数。

有任何想法吗?


142
2017-12-17 15:59


起源


没有执行至少两个查询就没有最好的方法来做到这一点。 - NARKOZ


答案:


Laravel> = 5.2:

User::inRandomOrder()->get();

Laravel 4.2.7 - 5.1:

User::orderByRaw("RAND()")->get();

Laravel 4.0 - 4.2.6:

User::orderBy(DB::raw('RAND()'))->get();

Laravel 3:

User::order_by(DB::raw('RAND()'))->get();

检查 本文 在MySQL随机行上。 Laravel 5.2支持这一点,对于旧版本,没有更好的解决方案 RAW查询

编辑1: 正如Double Gras所提到的,orderBy()不允许任何其他东西,然后是ASC或DESC 这个 更改。我相应地更新了答案。

编辑2: Laravel 5.2终于实现了 包装函数 为了这。它被称为 inRandomOrder()


372
2017-12-18 11:11



如果您想要单行,请将'get'替换为'first'。 - Collin Price
用于PostgreSQL 'RANDOM()' - dwenaus
警告:在大型数据集上,这非常慢,为我增加了大约900毫秒 - S..
我们可以分页吗? - Irfandi D. Vendy
但是,您可以在每个新页面上随机排序。这没有任何意义,因为它与按F5基本相同。 - aebersold


这很好用,

$model=Model::all()->random(1);

你也可以在随机函数中改变参数以获得多个记录。

注意:如果您有大量数据,则不推荐使用,因为这将首先获取所有行,然后返回随机值。


38
2018-03-05 21:11



性能方面的缺点是检索所有记录。 - Gras Double
这里随机调用集合对象而不是sql查询。随机函数在php端运行 - astroanu
@astroanu是的,但要填充该集合,将查询所有行。 - MetalFrog
我可能是错的,但是当传递给随机函数的参数与集合的大小相同时,这似乎不起作用。 - Brynn Bateman
这不好......这样你就可以检索所有记录并获得随机记录。如果您的表记录太多,这可能对您的应用程序造成不利影响。 - Anderson Silva


TL;博士: 它现在已经在Laravel中实现,请参阅下面的“编辑3”。


可悲的是,截至今天,有一些警告 ->orderBy(DB::raw('RAND()')) 建议解决方案

  • 它不是DB不可知的。例如SQLite和PostgreSQL使用 RANDOM()
  • 更糟糕的是,此解决方案不再适用 这种变化

    $direction = strtolower($direction) == 'asc' ? 'asc' : 'desc';


编辑: 现在你可以使用了 orderByRaw() 方法: ->orderByRaw('RAND()')。然而,这仍然不是DB不可知的。

FWIW,CodeIgniter实现了一个特殊的功能 RANDOM 排序方向,在构建查询时用正确的语法替换。它似乎也很容易实现。看起来我们有改进Laravel的候选人:)

更新:这是 问题 关于这个在GitHub上,我的待定 拉请求


编辑2: 让我们减少追逐。从Laravel 5.1.18开始,您可以将宏添加到查询构建器:

use Illuminate\Database\Query\Builder;

Builder::macro('orderByRandom', function () {

    $randomFunctions = [
        'mysql'  => 'RAND()',
        'pgsql'  => 'RANDOM()',
        'sqlite' => 'RANDOM()',
        'sqlsrv' => 'NEWID()',
    ];

    $driver = $this->getConnection()->getDriverName();

    return $this->orderByRaw($randomFunctions[$driver]);
});

用法:

User::where('active', 1)->orderByRandom()->limit(10)->get();

DB::table('users')->where('active', 1)->orderByRandom()->limit(10)->get();


编辑3: 最后!自Laravel 5.2.33(更新日志PR#13642)您可以使用本机方法 inRandomOrder()

User::where('active', 1)->inRandomOrder()->limit(10)->get();

DB::table('users')->where('active', 1)->inRandomOrder()->limit(10)->get();

21
2017-07-21 23:35



谢谢,第二次编辑真的是最好的答案! - Sander Visser
现在您可以看看第3次编辑;) - Gras Double
您应该将5.1宏名称更改为inRandomOrder,以便它向前兼容;)详细信息,详细信息:) - Sander Visser
这正是我在准备5.1项目之前做的一件事,然后再将其迁移到5.2。 - Gras Double


Laravel 4和5 该 order_by 被替换为 orderBy

所以,它应该是:

User::orderBy(DB::raw('RAND()'))->get();

15
2017-11-29 17:43



用户::排序依据(DB ::原始( 'RAND()')) - >获得(); - Darius Morawiec
它的工作表示感谢,但您能否提供一些有关其工作原理的信息? - alayli
你能更具体一点吗?什么样的信息? - Teodor Talov
这适用于laravel 5 - Angel Angel


您还可以使用具有流利和雄辩的order_by方法,如:

Posts::where_status(1)->order_by(DB::raw(''),DB::raw('RAND()')); 

这有点奇怪的用法,但有效。

编辑:正如@Alex所说,这种用法更清晰,也有效:

Posts::where_status(1)->order_by(DB::raw('RAND()'));

8
2017-12-22 23:04



这也有效,而且更干净.. - > order_by(\ DB :: raw('RAND()')) - Alex Naspo


对于Laravel 5.2> =

使用Eloquent方法:

inRandomOrder()

inRandomOrder方法可用于随机对查询结果进行排序。例如,您可以使用此方法来获取随机用户:

$randomUser = DB::table('users')
            ->inRandomOrder()
            ->first();

来自docs: https://laravel.com/docs/5.2/queries#ordering-grouping-limit-and-offset


6
2017-07-14 16:56





您可以使用:

ModelName::inRandomOrder()->first();

5
2017-08-11 09:52





在您的模型中添加:

public function scopeRandomize($query, $limit = 3, $exclude = [])
{
    $query = $query->whereRaw('RAND()<(SELECT ((?/COUNT(*))*10) FROM `products`)', [$limit])->orderByRaw('RAND()')->limit($limit);
    if (!empty($exclude)) {
        $query = $query->whereNotIn('id', $exclude);
    }
    return $query;
}

然后在路线/控制器

$data = YourModel::randomize(8)->get();

2
2017-07-14 01:21





还有 whereRaw('RAND()') 这样做,你可以链接 ->get()要么 ->first() 甚至发疯并添加 ->paginate(int)


1
2017-12-16 09:04