लारवेल - वाक्पटु या धाराप्रवाह यादृच्छिक पंक्ति


242

मैं लारेल ढांचे में एलोक्वेंट या धाराप्रवाह का उपयोग करके एक यादृच्छिक पंक्ति कैसे चुन सकता हूं?

मुझे पता है कि SQL का उपयोग करके, आप RAND () द्वारा ऑर्डर कर सकते हैं। हालाँकि, मैं प्रारंभिक क्वेरी से पहले रिकॉर्ड की संख्या पर एक गिनती किए बिना यादृच्छिक पंक्ति प्राप्त करना चाहूंगा ।

कोई विचार?


कम से कम दो प्रश्नों को निष्पादित किए बिना ऐसा करने का कोई सबसे अच्छा तरीका नहीं है।
NARKOZ

जवाबों:


584

लारवेल> = 5.2:

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

या

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

या रिकॉर्ड की विशिष्ट संख्या प्राप्त करने के लिए

//5 indicates the number of records
User::inRandomOrder()->limit(5)->get();

लारवेल 4.2.7 - 5.1:

User::orderByRaw("RAND()")->get();

लारवेल 4.0 - 4.2.6:

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

लारवेल 3:

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

MySQL यादृच्छिक पंक्तियों पर इस लेख की जाँच करें । लारवेल 5.2 इसका समर्थन करता है, पुराने संस्करण के लिए, फिर उपयोग करने से बेहतर कोई उपाय नहीं है रॉ क्वैरीज़

1 संपादित करें: जैसा कि डबल ग्रास द्वारा उल्लेख किया गया है, तब से आदेश () कुछ और फिर ASC या DESC की अनुमति नहीं देता है इस परिवर्तन के । मैंने उसी हिसाब से अपना जवाब अपडेट किया।

संपादित 2: लारवेल 5.2 अंत में इसके लिए एक आवरण समारोह लागू करता है। इसे InRandomOrder () कहा जाता है ।


81
यदि आप एकल पंक्ति चाहते हैं, तो 'पहले' से 'बदलें' को बदलें।
कॉलिन की कीमत

14
PostgreSQL के उपयोग के लिए'RANDOM()'
dwenaus

2
चेतावनी: बड़े डेटासेट पर यह बहुत धीमा है, मेरे लिए लगभग 900 एमएस जोड़ रहा है
एस ..

3
क्या हम इसे पृष्ठांकित कर सकते हैं?
इरफंडी डी। वेंडी

3
हालाँकि आप कर सकते हैं, लेकिन छँटाई हर नए पेज पर यादृच्छिक होगी। इसका कोई मतलब नहीं है क्योंकि यह अनिवार्य रूप से वही है जो आप F5 दबाते हैं।
aebersold

49

यह ठीक काम करता है,

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

आप एक से अधिक रिकॉर्ड प्राप्त करने के लिए यादृच्छिक फ़ंक्शन में तर्क भी बदल सकते हैं।

नोट: अनुशंसित नहीं है यदि आपके पास विशाल डेटा है क्योंकि यह पहले सभी पंक्तियों को प्राप्त करेगा और फिर यादृच्छिक मूल्य लौटाएगा।


61
एक प्रदर्शन-वार नकारात्मक यह है कि सभी रिकॉर्ड पुनर्प्राप्त किए जाते हैं।
ग्रास डबल

3
यहाँ यादृच्छिक को संग्रह वस्तु पर नहीं sql क्वेरी कहा जाता है। यादृच्छिक समारोह php की ओर से चलाया जाता है
astroanu

@astroanu राइट, लेकिन उस संग्रह को पॉप्युलेट करने के लिए, सभी पंक्तियों को उद्धृत किया गया है।
मेटलफ्रॉग

1
मैं गलत हो सकता है, लेकिन यह तब काम नहीं करता है जब रैंडम फ़ंक्शन को दिया गया पैरामीटर संग्रह के आकार के समान हो।
ब्रायन बॅटमैन

यह अच्छा नहीं है ... इस तरह आप सभी रिकॉर्ड्स को पुनः प्राप्त कर रहे हैं और एक यादृच्छिक प्राप्त कर रहे हैं। यदि आपकी तालिका में बहुत सारे रिकॉर्ड हैं, तो यह आपके ऐप के लिए बुरा हो सकता है।
एंडरसन सिल्वा

34

tl; dr: यह आजकल लारवेल में लागू किया गया है, नीचे "3 संपादित करें" देखें।


अफसोस की बात है, आज के रूप में ->orderBy(DB::raw('RAND()'))प्रस्तावित समाधान के साथ कुछ चेतावनी हैं:

  • यह डीबी-अज्ञेय नहीं है। जैसे SQLite और PostgreSQL का उपयोगRANDOM()
  • इससे भी बदतर, यह समाधान इस परिवर्तन के बाद से लागू नहीं है :

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


संपादित करें: अब आप ऑर्डरबेयर () विधि का उपयोग कर सकते हैं :->orderByRaw('RAND()') :। हालाँकि यह अभी भी डीबी-अज्ञेयवादी नहीं है।

FWIW, CodeIgniter एक विशेष लागू करता है RANDOM छँटाई दिशा को , जिसे क्वेरी बनाते समय सही व्याकरण से बदल दिया जाता है। इसके अलावा इसे लागू करना काफी आसान लगता है। लगता है कि हमारे पास लारवेल में सुधार के लिए एक उम्मीदवार है :)

अद्यतन: यहाँ GitHub पर इस बारे में समस्या है, और मेरा लंबित पुल अनुरोध है


संपादन 2: चलो पीछा काटते हैं। लारवेल 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 (के बाद से बदलाव का , पीआर # 13642 ) आप देशी पद्धति का उपयोग कर सकते हैं inRandomOrder():

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

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

आपको 5.1 मैक्रो का नाम इनरजैंडऑर्डर में बदलना चाहिए ताकि यह आगे संगत हो?) विवरण, विवरण :)
सैंडर

ठीक एक चीज़ जो मैंने 5.2 में माइग्रेट करने से पहले 5.1 प्रोजेक्ट तैयार करते समय की थी।
ग्रास डबल

यह इतना बड़ा जवाब है। अगर मैं एक जवाब fav कर सकता है, मैं करूँगा!
मवालिस्क

18

में Laravel 4 और 5order_by की जगहorderBy

तो, यह होना चाहिए:

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

उपयोगकर्ता :: orderBy (DB :: कच्चे ( 'रैंड ()')) -> get ();
दारजी

1
यह धन्यवाद काम करता है, लेकिन क्या आप कुछ जानकारी दे सकते हैं कि यह कैसे काम करता है?
अलयली

क्या आप थोड़ा और स्पष्ट कर सकते हैं? किस तरह की जानकारी?
तियोदोर तलोव


9

लारवेल के लिए 5.2> =

वाक् विधि का उपयोग करें:

inRandomOrder()

TheRandomOrder विधि का उपयोग क्वेरी परिणामों को यादृच्छिक रूप से सॉर्ट करने के लिए किया जा सकता है। उदाहरण के लिए, आप एक यादृच्छिक उपयोगकर्ता लाने के लिए इस विधि का उपयोग कर सकते हैं:

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

डॉक्स से: https://laravel.com/docs/5.2/queries#ordering-grouping-limit-and-inset


कोर्स :: inRandomOrder () -> ले (20) -> get (); मेरे लिए काम नहीं कर रहा है - Find.php लाइन 219 में खराब सॉर्ट विनिर्देश
MJ

1
यह मॉडल कारखानों या डीबी सीडिंग के लिए उपयोगी है
सालेह महमूद

8

आप भी धाराप्रवाह और वाक्पटु जैसे के साथ order_by विधि का उपयोग कर सकते हैं:

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

यह थोड़ा अजीब प्रयोग है, लेकिन काम करता है।

संपादित करें: जैसा कि @Alex ने कहा, यह उपयोग क्लीनर है और यह भी काम करता है:

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

3
यह अच्छी तरह से काम करता है और थोड़ा साफ होता है .. -> ऑर्डर_बाय (\ DB :: कच्चा ('RAND ()'))
एलेक्स नास्पो


3

आप आसानी से इस कमांड का उपयोग कर सकते हैं:

// सवाल: मॉडल का नाम
// डीबी से 10 पंक्तियों को फेरबदल में रिकॉर्ड करें ...

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

3

मैं पहले निर्दिष्ट करना या विफल होना पसंद करता हूं:

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

3

लारवेल के पास परिणामों के क्रम में फेरबदल करने के लिए एक अंतर्निहित पद्धति है।

यहाँ प्रलेखन से एक उद्धरण है:

shuffle()

फेरबदल विधि बेतरतीब ढंग से संग्रह में आइटम फेरबदल:

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

$shuffled = $collection->shuffle();

$shuffled->all();

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

आप यहाँ दस्तावेज़ देख सकते हैं ।


2

अपने मॉडल में इसे जोड़ें:

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

वहाँ भी है whereRaw('RAND()')जो एक ही करता है सकते हैं तो चेन, आप ->get()या ->first()भी या पागल जाने के लिए और जोड़ने ->paginate(int)


0

मेरे पास हजारों रिकॉर्ड्स के साथ तालिका है, इसलिए मुझे कुछ तेज चाहिए। यह छद्म यादृच्छिक पंक्ति के लिए मेरा कोड है:

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

इसके साथ समस्या यह है कि यदि $countइनमें से पहली से अधिक आईडी वाली कई पंक्तियाँ हैं , जिन्हें कभी भी पुनर्प्राप्त किया जाएगा, और इसलिए यह किसी भी अन्य पंक्ति की तुलना में पुनर्प्राप्त होने की अधिक संभावना होगी।
केमिका
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.