【问题标题】:how get random row laravel-5如何获得随机行 laravel-5
【发布时间】:2015-01-14 23:37:36
【问题描述】:

在 L-4 中很简单:

$random_quote = Quotation::all()->random(1);

但现在在 L-5 中,这篇文章中描述的任何一种方法都不起作用: Laravel - Eloquent or Fluent random row

我的视图文件只是空白。

【问题讨论】:

  • 你试过什么代码?它有效,可能你错过了什么
  • 顺便说一句,这在性能方面真的很糟糕。
  • 你能分享一个性能方面的方法吗?我有c。数据库中的30 000句名言...

标签: random eloquent laravel-5


【解决方案1】:

这些有效,但可能您没有使用正确的namespace,只需在您的class 名称顶部使用use 语句,如下所示:

<?php namespace SomeNamespace;

use App\Quotation; // Says "Quotation.php" is in "App" folder (By default in L-5.0)

class someClass {
    //...
}

然后你可以在你的method 中使用这样的东西:

// You may add: use DB; at the top to use DB instead of \DB
$random_quote = Quotation::orderBy(\DB::raw('RAND()'))->first();

或者这个:

$random_quote = Quotation::orderByRaw("RAND()")->first();

更新(自 Laravel - 5.2 起):

$random_quote = Quotation::inRandomOrder()->first();

【讨论】:

  • 我们应该把 first() 而不是 get() 我打印字符串,变量是一个数组。这就是为什么视图是空白的。
  • ORDER BY RAND() 实际上真的很慢,我的意思是真的,真的,...,真的很慢。即使在有 400 行的表上,我也开始注意到差异。
  • ::inRandomOrder() 无论如何都会解析为“ORDER BY RAND()”。
  • $objects = Model::inRandomOrder()-&gt;first(); 是最干净的方式!谢谢。
【解决方案2】:

random() 在 5.2 中出现错误,所以你可以改用 inRandomOrder https://laravel.com/docs/5.2/queries#ordering-grouping-limit-and-offset

它可以像 Eloquent 一样工作

Model::inRandomOrder()->first()

【讨论】:

  • 现在 THIS 应该是公认的答案。它不是特定于数据库的,并且利用了框架功能。 +1
【解决方案3】:

Laravel 5.4 更新

New randomsorting in Laravel 5.4 -&gt;inRandomOrder()-&gt;first()

【讨论】:

  • 这对我很有帮助,不过我遇到了一个问题,我只想在页面上显示一个引用和作者(正在发生),但是与每个引用相关的 id 也出现了,怎么办我排除了 id?
【解决方案4】:

LARAVEL 5.3 更新

我很高兴发现这现在是一个原生查询功能! :D

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

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

不幸的是,这些答案都没有充分利用 Laravel 5 的集合。如果您像我一样从 Google 来到这里,正在寻找一个完全原生的解决方案,请看下面!

The Alpha 的答案存在数据库依赖缺陷,正如他所指出的,Benjamin 的答案在删除中间的行时可能会造成问题。极不可能,但仍有可能。

这是在 Laravel 5+ 中选择随机行的单行解决方案

// The setup
$numberOfRows = 4;
$models = Model::all(); // or use a ::where()->get();

// And the actual randomisation line
$randRows = $models->shuffle()->slice(0,numberOfRows);

瞧——快乐的编码!当你看到它时投票给它,这样它就会在页面上出现:)

【讨论】:

  • 虽然这肯定行得通,但是当您只想要一行时,获得一个表的所有结果就太过分了。如果您有非常大的表,则会大大降低性能。
  • 只需使用 ->take(100)?
  • 那么你只会得到前100行的随机一行!
  • 好吧,公平点!首先执行 ->count(),然后生成一个介于 1 和 $count 之间的随机整数,然后将其用于 ::find() - 问题解决了,对吧?
  • 假设您有 500 行。您将选择一条记录:mt_rand(1,500),然后使用 find。引用::find(15)。如果 id 为 15 的行被删除了怎么办?所以你知道你有 500 行,但你不知道是否有一条记录与 1 到 500 之间的每个 id 相关联。
【解决方案5】:

orderByRaw('RAND()') 有 2 个问题:

  1. 它依赖于 MySQL 服务器
  2. 在大型表上可能会很慢(获取所有行)

这是我使用的解决方案,似乎更好一些:

$cnt = $records->count();
if ($cnt == 0)
    return;

$randIndex = rand(0, $cnt-1);
$obj = $records->skip($randIndex)->take(1)->first();

编辑:请注意,如果在“count()”和“skip()”之间删除了一些记录,则在并行请求数据库的情况下,我的解决方案可能会出现问题(如果没有运气,则会崩溃)。

【讨论】:

    【解决方案6】:

    我会使用Benjamin's idea 来实现这一点。一个Query Scope 感觉很合适,所以它可以重复使用,它属于你正常的 Eloquent 使用。

    注意:In Eloquent 5.2, there is built in support for global scopes.

    我将创建一个模型可以利用的特征,但您可以直接将 scopeRandom 方法添加到您的特定模型。

    /app/GlobalScopes.php

    <?php
    
    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    
    trait GlobalScopes
    {
        public function scopeRandom($query){
            $totalRows = static::count() - 1;
            $skip = $totalRows > 0 ? mt_rand(0, $totalRows) : 0;
    
            return  $query->skip($skip)->take(1);
        }
    }
    

    然后,您要使用全局作用域的每个模型,在类中命名特征。

    /app/Quotation.php

    <?php
    
    namespace App;
    
    use Illuminate\Database\Eloquent\Model;
    
    class Quotation extends Model
    {
        use GlobalScopes;
    
        //...
    }
    

    使用中:

    $randomQuote = \Quotation::random()->first();
    

    【讨论】:

    • 聪明的解决方案和此页面上的最佳 Laravel 特定答案。
    【解决方案7】:

    在 Laravel 5.1(和 Laravel 5.2)中,Eloquent 构建器返回的 Collection 类中有一个 random 方法。

    https://laravel.com/docs/5.1/collections#available-methods

    所以你的电话

    $random_quote = Quotation::all()->random(1);
    

    $random_quote = Quotation::where('column', 'value')->get()->random(1);
    

    应该可以正常工作。

    【讨论】:

    • $r = Quotation::all()-&gt;random(1); 确实有效,但它首先执行select * from quotations...如果有很多报价可能会很慢...
    【解决方案8】:

    Laravel 5.4

    1) 如果需要一个随机模型:

    $object = Model::all()->random();
    

    2) 如果需要多个随机模型:

    $object = Model::all()->random($n); //$n - number of elements
                                        //$object - collection
    

    注释:调用 $collection->random(1) 现在将返回一个包含一个项目的新集合实例。如果不提供任何参数,此方法将只返回一个对象。

    文档参考:https://laravel.com/docs/5.4/collections#method-random

    【讨论】:

    【解决方案9】:
    orderByRaw('RAND()')
    

    注意:它将从查询的其余部分中取出所有行,因此,如果您有一个大表而在同一查询中没有其他过滤器,则性能会很差,否则这是您的选择

    【讨论】:

      【解决方案10】:

      您可以使用random() 方法,该方法“从集合中返回一个随机项”:

      Product::where('city_id', $discount->product->city)
              ->get()
              ->random(1);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-12-29
        • 1970-01-01
        • 2020-02-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多