Domanda Laravel - Eloquent o Fluent random row


Come posso selezionare una riga casuale usando Eloquent o Fluent nel framework di Laravel?

So che usando SQL, puoi fare ordine con RAND (). Tuttavia, mi piacerebbe ottenere la riga casuale senza facendo un conteggio sul numero di record prima della query iniziale.

Qualche idea?


138
2017-12-17 15:59


origine


risposte:


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

Dai un'occhiata Questo articolo su righe casuali di MySQL. Laravel 5.2 supporta questo, per le versioni precedenti, non esiste una soluzione migliore da utilizzare Query RAW.

modifica 1: Come menzionato da Double Gras, orderBy () non consente nient'altro da allora ASC o DESC Questo modificare. Ho aggiornato la mia risposta di conseguenza.

modifica 2: Laravel 5.2 finalmente implementa una funzione wrapper per questo. È chiamato inRandomOrder ().


366
2017-12-18 11:11



Funziona bene,

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

puoi anche cambiare argomento in funzione casuale per ottenere più di un record.

Nota: sconsigliato se si dispone di dati enormi poiché questo preleverà prima tutte le righe e poi restituirà un valore casuale.


38
2018-03-05 21:11



tl; dr: Al giorno d'oggi è implementato in Laravel, vedi "modifica 3" di seguito.


Purtroppo, ad oggi ci sono alcuni avvertimenti con il ->orderBy(DB::raw('RAND()')) la soluzione proposta:

  • Non è DB-agnostico. per esempio. Uso di SQLite e PostgreSQL RANDOM()
  • Ancora peggio, questa soluzione non è più applicabile da allora questo cambiamento:

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


modificare: Ora puoi usare il orderByRaw () metodo: ->orderByRaw('RAND()'). Tuttavia questo non è ancora DB-agnostico.

FWIW, CodeIgniter implementa uno speciale RANDOM direzione di ordinamento, che viene sostituita con la grammatica corretta quando si crea una query. Inoltre sembra essere abbastanza facile da implementare. Sembra che abbiamo un candidato per migliorare Laravel :)

aggiornamento: ecco il problema su questo su GitHub, e il mio in sospeso richiesta di pull.


modifica 2: Let's tagliare l'inseguimento. Dal momento che Laravel 5.1.18 è possibile aggiungere macro al generatore di query:

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]);
});

Uso:

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

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


modifica 3: Finalmente! Dal momento che Laravel 5.2.33 (changelog, PR # 13642) puoi usare il metodo nativo 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



In Laravel 4 e 5 il order_by è sostituito da orderBy

Quindi, dovrebbe essere:

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

15
2017-11-29 17:43



Puoi anche usare il metodo order_by con fluente ed eloquente come:

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

Questo è un uso un po 'strano, ma funziona.

Modifica: come ha detto @Alex, questo utilizzo è più pulito e funziona anche:

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

8
2017-12-22 23:04



Per Laravel 5.2> =

usa il metodo Eloquent:

inRandomOrder()

Il metodo inRandomOrder può essere utilizzato per ordinare casualmente i risultati della query. Ad esempio, puoi utilizzare questo metodo per recuperare un utente casuale:

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

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


6
2017-07-14 16:56



Puoi usare:

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

5
2017-08-11 09:52