wake-up-neo.com

Laravel - eloquent oder fließend zufällige Reihe

Wie kann ich mit Eloquent oder Fluent in Laravel eine zufällige Zeile auswählen?

Ich weiß, dass Sie mithilfe von SQL eine Reihenfolge nach Rand () ausführen können. Ich möchte jedoch die zufällige Zeile erhalten, ohne dass die Anzahl der Datensätze vor der ersten Abfrage zählt.

Irgendwelche Ideen?

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

Laravel 3:

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

Überprüfen Sie diesen Artikel in MySQL-Zeilen. Laravel 5.2 unterstützt dies. Für ältere Versionen gibt es keine bessere Lösung als die Verwendung von RAW Queries .

edit 1: Wie von Double Gras erwähnt, erlaubt orderBy () nichts anderes als ASC oder DESC seit this change. Ich habe meine Antwort entsprechend aktualisiert.

edit 2: Laravel 5.2 implementiert schließlich eine Wrapper-Funktion dafür. Es heißt inRandomOrder ().

425
aebersold

Das funktioniert gut,

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

sie können auch das Argument in der Zufallsfunktion ändern, um mehr als einen Datensatz zu erhalten.

Hinweis: Nicht empfehlenswert, wenn Sie über große Daten verfügen, da dies alle Zeilen zuerst abruft und dann einen zufälligen Wert zurückgibt.

41
manish

tl; dr: Es ist heutzutage in Laravel implementiert, siehe "edit 3" unten.


Leider gibt es ab heute einige Einschränkungen bei der vorgeschlagenen Lösung ->orderBy(DB::raw('Rand()')):

  • Es ist nicht DB-unabhängig. z.B. SQLite und PostgreSQL verwenden RANDOM()
  • Schlimmer noch, diese Lösung ist nicht mehr anwendbar seit diese Änderung :

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


edit: Jetzt können Sie die orderByRaw () -Methode verwenden: ->orderByRaw('Rand()'). Dies ist jedoch immer noch nicht DB-unabhängig.

FWIW, CodeIgniter implementiert eine spezielle Sortierrichtung RANDOM, die beim Erstellen von Abfragen durch die richtige Grammatik ersetzt wird. Auch scheint es ziemlich einfach zu implementieren zu sein. Sieht so aus, als hätten wir einen Kandidaten zur Verbesserung Laravel :)

update: Hier ist das Problem zu diesem Thema auf GitHub und mein ausstehendes Pull-Anfrage .


edit 2: Lass uns die Verfolgung beenden. Seit Laravel 5.1.18 können Sie dem Abfrage-Generator Makros hinzufügen:

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

Verwendungszweck:

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

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


edit 3: Endlich! Seit Laravel 5.2.33 ( changelog , PR # 13642 ) können Sie die native Methode inRandomOrder() verwenden:

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

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

In Laravel 4 und 5 wird der order_by durch orderBy ersetzt

So sollte es sein:

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

Sie können verwenden:

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

Sie können auch die order_by-Methode mit fließend und eloquent verwenden, wie:

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

Dies ist ein bisschen komisch, funktioniert aber.

Edit: Wie @Alex sagte, ist diese Verwendung sauberer und funktioniert auch:

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

Für Laravel 5.2> =

verwenden Sie die Eloquent-Methode: 

inRandomOrder()

Die inRandomOrder-Methode kann verwendet werden, um die Abfrageergebnisse zufällig zu sortieren. Beispielsweise können Sie diese Methode verwenden, um einen zufälligen Benutzer abzurufen:

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

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

8
Manuel Azar

Bei Ihrem Modell fügen Sie folgendes hinzu:

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

dann bei route/controller

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

Es gibt auch whereRaw('Rand()'), die dasselbe tun, Sie können dann ->get() oder ->first() verketten oder sogar verrückt werden und ->paginate(int) hinzufügen.

2
ctf0

Ich habe einen Tisch mit Tausenden von Datensätzen, also brauche ich schnell etwas. Dies ist mein Code für eine zufällige Pseudozeile:

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

Sie können diesen Befehl leicht verwenden:

// Frage: Name des Modells
// Nimm 10 Zeilen von DB In Shuffle-Datensätzen ...

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

Verwenden Sie die Laravel-Funktion 

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