LaravelフレームワークでEloquentまたはFluentを使用してランダムな行を選択する方法を教えてください。
SQLを使うことで、Rand()で並べることができることを私は知っています。しかし、私はランダムな行を取得したいなしで最初の問い合わせの前にレコード数を数えています。
何か案は?
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()と呼ばれます。
これはうまくいきます、
$model=Model::all()->random(1)->first();
ランダム関数で引数を変更して複数のレコードを取得することもできます。
注:巨大なデータがある場合は、最初にすべての行を取得してからランダムな値を返すため、お勧めできません。
tl; dr:今日ではLaravelに実装されています。下記の「編集3」を参照してください。
残念ながら、今日の時点で提案されている->orderBy(DB::raw('Rand()'))
解決策にはいくつかの注意点があります。
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( changelog 、 PR#13642 )以降、ネイティブメソッドinRandomOrder()
を使用できます。
User::where('active', 1)->inRandomOrder()->limit(10)->get();
DB::table('users')->where('active', 1)->inRandomOrder()->limit(10)->get();
Laravel 4 and 5order_by
はorderBy
に置き換えられました。
だから、それはする必要があります:
User::orderBy(DB::raw('Rand()'))->get();
あなたは使うことができます:
ModelName::inRandomOrder()->first();
次のように流暢で雄弁なorder_byメソッドを使うこともできます。
Posts::where_status(1)->order_by(DB::raw(''),DB::raw('Rand()'));
これは少し変な使い方ですが、うまくいきます。
編集:@アレックスが言ったように、この使用法はよりきれいでそしてまたうまくいきます:
Posts::where_status(1)->order_by(DB::raw('Rand()'));
Laravel 5.2> =の場合
eloquentメソッドを使用してください。
inRandomOrder()
InRandomOrderメソッドは、クエリ結果をランダムにソートするために使用できます。例えば、あなたはランダムなユーザを取得するためにこのメソッドを使うかもしれません:
$randomUser = DB::table('users')
->inRandomOrder()
->first();
ドキュメントから: https://laravel.com/docs/5.2/queries#ordering-grouping-limit-and-offset
あなたのモデルでこれを追加します。
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();
同じことをするwhereRaw('Rand()')
もあります、それから->get()
や->first()
をチェーニングすることができ、あるいは狂って->paginate(int)
を追加することさえできます。
あなたは簡単にこのコマンドを使うことができます:
//質問:モデル名
//レコードをシャッフルレコードでDBから10行取得します...
$questions = Question::orderByRaw('Rand()')->take(10)->get();
私は何千ものレコードを含むテーブルを持っているので、速いものが必要です。これは私の疑似乱数行のコードです。
// 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();