web-dev-qa-db-ja.com

Laravel - 流暢または流暢なランダム行

LaravelフレームワークでEloquentまたはFluentを使用してランダムな行を選択する方法を教えてください。

SQLを使うことで、Rand()で並べることができることを私は知っています。しかし、私はランダムな行を取得したいなしで最初の問い合わせの前にレコード数を数えています。

何か案は?

188
DigitalWM

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();

階級3:

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

MySQLのランダムな行でこの記事をチェックしてください。 Laravel 5.2ではこれがサポートされています。古いバージョンでは、 RAW Queries を使用した場合より良い解決策はありません。

edit 1:Double Grasが述べたように、orderBy()はASCやDESC以外には何も許可していません this change 。私はそれに応じて答えを更新しました。

編集2:Laravel 5.2がついに ラッパー関数 を実装しました。それはinRandomOrder()と呼ばれます

469
aebersold

これはうまくいきます、

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

ランダム関数で引数を変更して複数のレコードを取得することもできます。

注:巨大なデータがある場合は、最初にすべての行を取得してからランダムな値を返すため、お勧めできません。

42
manish

tl; dr:今日ではLaravelに実装されています。下記の「編集3」を参照してください。


残念ながら、今日の時点で提案されている->orderBy(DB::raw('Rand()'))解決策にはいくつかの注意点があります。

  • DBにとらわれません。例えばSQLiteとPostgreSQLはRANDOM()を使います
  • さらに悪いことに、この解決法は この変更 以来もはや適用できません。

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


edit:これで、 orderByRaw() メソッド:->orderByRaw('Rand()')を使用できます。しかし、これはまだDBにとらわれません。

FWIW、CodeIgniterは特別なRANDOMソート方向を実装しています。これはクエリを構築するときに正しい文法に置き換えられます。実装もかなり簡単なようです。 Laravel :)を改善する候補があるようです。

更新:これがGitHubでの issue 、そして私の保留中の pull request です。


編集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( changelogPR#13642 )以降、ネイティブメソッドinRandomOrder()を使用できます。

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

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

Laravel 4 and 5order_byorderByに置き換えられました。

だから、それはする必要があります:

User::orderBy(DB::raw('Rand()'))->get();
17
Teodor Talov

あなたは使うことができます

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

次のように流暢で雄弁なorder_byメソッドを使うこともできます。

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

これは少し変な使い方ですが、うまくいきます。

編集:@アレックスが言ったように、この使用法はよりきれいでそしてまたうまくいきます:

Posts::where_status(1)->order_by(DB::raw('Rand()'));
8
Bilal Gultekin

Laravel 5.2> =の場合

eloquentメソッドを使用してください。

inRandomOrder()

InRandomOrderメソッドは、クエリ結果をランダムにソートするために使用できます。例えば、あなたはランダムなユーザを取得するためにこのメソッドを使うかもしれません:

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

ドキュメントから: https://laravel.com/docs/5.2/queries#ordering-grouping-limit-and-offset

8
Manuel Azar

あなたのモデルでこれを追加します。

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
Neto

同じことをするwhereRaw('Rand()')もあります、それから->get()->first()をチェーニングすることができ、あるいは狂って->paginate(int)を追加することさえできます。

2
ctf0

あなたは簡単にこのコマンドを使うことができます:

//質問:モデル名
//レコードをシャッフルレコードでDBから10行取得します...

$questions = Question::orderByRaw('Rand()')->take(10)->get();
1
hosein azimi

私は何千ものレコードを含むテーブルを持っているので、速いものが必要です。これは私の疑似乱数行のコードです。

// count all rows with flag active = 1
$count = MyModel::where('active', '=', '1')->count(); 

// get random id
$random_id = Rand(1, $count - 1);  

// get first record after random id
$data = MyModel::where('active', '=', '1')->where('id', '>', $random_id)->take(1)->first(); 

Laravel関数を使う

ModelName::inRandomOrder()->first();
0
Kamlesh Paul