Laravel - Rasgele veya Akıcı rastgele satır


242

Laravel çerçevesinde Eloquent veya Fluent kullanarak nasıl rastgele bir satır seçebilirim?

SQL kullanarak, RAND () ile sipariş yapabilirsiniz biliyorum. Ancak, ben rastgele satır almak istiyorum olmadan önce ilk sorguya kayıtların sayısı için bir sayım yapıyor.

Herhangi bir fikir?


Bunu en az iki sorgu yürütmeden yapmanın en iyi yolu yoktur.
NARKOZ

Yanıtlar:


587

Laravel> = 5.2:

User::all()->random();
User::all()->random(10); // The amount of items you wish to receive

veya

User::inRandomOrder()->get();

veya Belirli sayıda kayıt almak için

//5 indicates the number of records
User::inRandomOrder()->limit(5)->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();

MySQL rastgele satırlarıyla ilgili bu makaleye göz atın . Laravel 5.2 bunu desteklemektedir, eski sürüm için RAW Sorguları kullanmaktan daha iyi bir çözüm yoktur .

edit 1: Double Gras tarafından belirtildiği gibi, orderBy () bu değişiklikten sonra ASC veya DESC'den başka bir şeye izin vermez . Cevabımı buna göre güncelledim.

edit 2: Laravel 5.2 sonunda bunun için bir sarmalayıcı işlevi uygular . Buna inRandomOrder () denir .


81
Tek bir satır istiyorsanız 'get' ifadesini 'first' ile değiştirin.
Collin Price

14
PostgreSQL kullanımı için'RANDOM()'
dwenaus

2
Uyarı: büyük veri kümelerinde bu çok yavaş, benim için yaklaşık 900 ms ekleyerek
S ..

3
Bunu sayfalandırabilir miyiz?
Irfandi D. Vendy

3
Bununla birlikte, sıralama her yeni sayfada rastgele olacaktır. Bu hiç mantıklı değil çünkü aslında F5 tuşuna basmanızla aynı.
aebersold

49

Bu gayet iyi çalışıyor,

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

birden fazla kayıt almak için rasgele işlevdeki bağımsız değişkeni de değiştirebilirsiniz.

Not: büyük verileriniz varsa önerilmez, çünkü bu önce tüm satırları getirir ve ardından rastgele değer döndürür.


61
Performans açısından dezavantaj, tüm kayıtların geri alınmasıdır.
Gras Double

3
burada rastgele sql sorgusu değil toplama nesnesinde çağrılır. rastgele işlevi php tarafında çalıştırılır
astroanu

@astroanu Doğru, ancak bu koleksiyonu doldurmak için tüm satırlar sorgulanır.
MetalFrog

1
Yanlış olabilirim, ancak parametre rastgele işleve iletilen koleksiyonun boyutuyla aynı olduğunda bu işe yaramıyor gibi görünüyor.
Brynn Bateman

Bu iyi değil ... Bu şekilde tüm kayıtları alıyorsunuz ve rastgele bir kayıt alıyorsunuz. Tablonuzda çok fazla kayıt varsa, bu durum uygulamanız için kötü olabilir.
Anderson Silva

34

tl; dr: Bugünlerde Laravel'e uygulandı, aşağıdaki "düzenle 3" e bakın.


Ne yazık ki, bugün itibariyle ->orderBy(DB::raw('RAND()'))önerilen çözümle ilgili bazı uyarılar var :

  • DB-agnostik değil. örneğin SQLite ve PostgreSQL kullanımıRANDOM()
  • Daha da kötüsü, bu değişiklik bu değişiklikten bu yana artık geçerli değil :

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


düzenleme: Artık kullanabilirsiniz orderByRaw () yöntemini: ->orderByRaw('RAND()'). Ancak bu hala DB agnostik değildir.

FWIW, CodeIgniter özel bir uygulama RANDOM , sorgu oluşturulurken doğru dilbilgisi ile değiştirilen sıralama yönü . Ayrıca uygulanması oldukça kolay görünüyor. Görünüşe göre Laravel'i geliştirmek için bir adayımız var :)

Güncelleme: İşte GitHub'da bununla ilgili sorun ve bekleyen çekme isteğim .


düzenlemek 2: Let's cut the chase. Laravel 5.1.18'den bu yana, sorgu oluşturucuya makrolar ekleyebilirsiniz:

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

Kullanımı:

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

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


edit 3: Sonunda! Laravel 5.2.33'ten ( changelog , PR # 13642 ) yerel yöntemi kullanabilirsiniz inRandomOrder():

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

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

5.1 makro adını inRandomOrder olarak değiştirmelisiniz, böylece ileri uyumludur;) Ayrıntılar, ayrıntılar :)
Sander Visser

Bu, 5.1 projesine 5.2'ye geçmeden önce yaptığım bir şey.
Gras Double

Bu harika bir cevap. Bir cevabı tercih etseydim, yapardım!
mwallisch

18

Gelen laravel 4 ve 5order_by ile değiştirilirorderBy

Bu yüzden olmalı:

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

Kullanıcı :: orderBy (DB :: çiğ ( 'RAND ()')) -> get ();
Darius

1
Teşekkürler, ama bunun nasıl çalıştığı hakkında bilgi verebilir misiniz?
alayli

Biraz daha spesifik olabilir misiniz? Ne tür bilgiler?
Teodor Talov


9

Laravel 5.2 için> =

Eloquent yöntemini kullanın:

inRandomOrder()

Sorgu sonuçlarını rastgele sıralamak için inRandomOrder yöntemi kullanılabilir. Örneğin, rastgele bir kullanıcı getirmek için bu yöntemi kullanabilirsiniz:

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

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


Ders :: inRandomOrder () -> almak (20) -> get (); Benim için çalışmıyor - Find.php satır 219
MJ

1
Bu model fabrikalar veya db tohumlama için yararlıdır
Saleh Mahmood

8

Ayrıca, order_by yöntemini aşağıdaki gibi akıcı ve etkili bir şekilde kullanabilirsiniz:

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

Bu biraz garip bir kullanımdır, ancak işe yarar.

Düzenleme: @Alex'in dediği gibi, bu kullanım daha temizdir ve ayrıca çalışır:

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

3
bu da işe yarıyor ve biraz daha temiz .. -> order_by (\ DB :: raw ('RAND ()'))
Alex Naspo


3

Bu komutu kolayca kullanabilirsiniz:

// Soru: Model adı
// DB'den 10 satır al Karışık kayıtlarda ...

$questions = Question::orderByRaw('RAND()')->take(10)->get();

3

Önce belirtmeyi veya başarısız olmayı tercih ederim:

$collection = YourModelName::inRandomOrder()
  ->firstOrFail();

3

Laravel, sonuçların sırasını karıştırmak için yerleşik bir yönteme sahiptir.

İşte belgelerden bir alıntı:

shuffle()

Karışık yöntem, koleksiyondaki öğeleri rastgele karıştırır:

$collection = collect([1, 2, 3, 4, 5]);

$shuffled = $collection->shuffle();

$shuffled->all();

// [3, 2, 5, 1, 4] - (generated randomly)

Belgeleri burada görebilirsiniz .


2

Modelinize şunu ekleyin:

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

sonra rota / denetleyicide

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

2

Orada da whereRaw('RAND()')sen zinciri sonra, aynısını yapar hangi olabilir ->get()veya ->first()hatta deli gidip ekleyin ->paginate(int).


0

Binlerce kayıt içeren masam var, bu yüzden hızlı bir şeye ihtiyacım var. Bu sahte rasgele satır için benim kod:

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

Buradaki sorun, id'lerin $countyalnızca ilkinden daha büyük birden çok satırı varsa ve herhangi bir satırdan daha büyük olasılıkla alınabileceğidir.
kemika
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.