ฉันจะเลือกแถวสุ่มโดยใช้ Eloquent หรือ Fluent ในกรอบงาน Laravel ได้อย่างไร
ฉันรู้ว่าโดยใช้ SQL คุณสามารถสั่งซื้อโดย RAND () อย่างไรก็ตามฉันต้องการรับแถวสุ่มโดยไม่นับจำนวนระเบียนก่อนที่จะเริ่มต้นแบบสอบถาม
ความคิดใด ๆ
ฉันจะเลือกแถวสุ่มโดยใช้ Eloquent หรือ Fluent ในกรอบงาน Laravel ได้อย่างไร
ฉันรู้ว่าโดยใช้ SQL คุณสามารถสั่งซื้อโดย RAND () อย่างไรก็ตามฉันต้องการรับแถวสุ่มโดยไม่นับจำนวนระเบียนก่อนที่จะเริ่มต้นแบบสอบถาม
ความคิดใด ๆ
คำตอบ:
Laravel> = 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();
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 Laravel 5.2 สนับสนุนนี้สำหรับรุ่นเก่าไม่มีการแก้ปัญหาที่ดีกว่าแล้วใช้RAW แบบสอบถาม
แก้ไข 1:ตามที่ระบุไว้โดยดับเบิล Gras, orderBy () ไม่ยอมให้อะไรอื่นแล้วหรือ ASC DESC ตั้งแต่นี้การเปลี่ยนแปลง ฉันปรับปรุงคำตอบของฉันตาม
แก้ไข 2: Laravel 5.2 ในที่สุดก็ใช้ฟังก์ชั่น wrapperสำหรับสิ่งนี้ มันเรียกว่าinRandomOrder ()
'RANDOM()'
มันใช้งานได้ดี
$model=Model::all()->random(1)->first();
นอกจากนี้คุณยังสามารถเปลี่ยนอาร์กิวเมนต์ในฟังก์ชันสุ่มเพื่อรับมากกว่าหนึ่งระเบียน
หมายเหตุ: ไม่แนะนำหากคุณมีข้อมูลจำนวนมากเนื่องจากจะเป็นการดึงข้อมูลแถวทั้งหมดก่อนแล้วจึงส่งกลับค่าสุ่ม
tl; dr:ปัจจุบันมีการใช้งานใน Laravel แล้วโปรดดู "แก้ไข 3" ด้านล่าง
น่าเศร้า ณ วันนี้มีข้อแม้บางอย่างที่มี->orderBy(DB::raw('RAND()'))
วิธีแก้ปัญหาที่เสนอ:
RANDOM()
ยิ่งกว่านั้นโซลูชันนี้ใช้ไม่ได้อีกต่อไปนับตั้งแต่การเปลี่ยนแปลงนี้ :
$direction = strtolower($direction) == 'asc' ? 'asc' : 'desc';
แก้ไข:ตอนนี้คุณสามารถใช้เมธอด orderByRaw () :->orderByRaw('RAND()')
วิธีการ:อย่างไรก็ตามเรื่องนี้ยังคงไม่เชื่อเรื่อง DB
FWIW, CodeIgniter ดำเนินการพิเศษ RANDOM
ทิศทางการเรียงลำดับซึ่งจะถูกแทนที่ด้วยไวยากรณ์ที่ถูกต้องเมื่อสร้างแบบสอบถาม นอกจากนี้ยังดูเหมือนว่าจะใช้งานค่อนข้างง่าย ดูเหมือนว่าเรามีผู้สมัครเพื่อปรับปรุง Laravel :)
อัปเดต: นี่คือปัญหาเกี่ยวกับเรื่องนี้บน GitHub และอยู่ระหว่างการพิจารณาของฉันคำขอดึง
แก้ไข 2: Let's ตัดการไล่ล่า ตั้งแต่ 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 และ 5order_by
จะถูกแทนที่ด้วยorderBy
ดังนั้นควร:
User::orderBy(DB::raw('RAND()'))->get();
คุณสามารถใช้ :
ModelName::inRandomOrder()->first();
สำหรับ Laravel 5.2> =
ใช้วิธี Eloquent:
inRandomOrder()
อาจใช้วิธีการ inRandomOrder เพื่อเรียงลำดับผลลัพธ์แบบสอบถามโดยการสุ่ม ตัวอย่างเช่นคุณอาจใช้วิธีนี้เพื่อดึงข้อมูลผู้ใช้แบบสุ่ม:
$randomUser = DB::table('users')
->inRandomOrder()
->first();
จากเอกสาร: https://laravel.com/docs/5.2/queries#ordering-grouping-limit-and-offset
คุณยังสามารถใช้วิธี order_by อย่างคล่องแคล่วและมีคารมคมคายเช่น:
Posts::where_status(1)->order_by(DB::raw(''),DB::raw('RAND()'));
นี่เป็นการใช้งานที่แปลกเล็กน้อย แต่ใช้งานได้
แก้ไข: ดังที่ @Alex กล่าวว่าการใช้งานนี้สะอาดและใช้งานได้:
Posts::where_status(1)->order_by(DB::raw('RAND()'));
ใช้ฟังก์ชั่น Laravel
ModelName::inRandomOrder()->first();
คุณสามารถใช้คำสั่งนี้:
// คำถาม: ชื่อรุ่น
// จด 10 แถวจาก DB In shuffle records ...
$questions = Question::orderByRaw('RAND()')->take(10)->get();
ฉันต้องการระบุก่อนหรือล้มเหลว:
$collection = YourModelName::inRandomOrder()
->firstOrFail();
Laravel มีวิธีการในตัวเพื่อสลับลำดับของผลลัพธ์
นี่คือคำพูดจากเอกสาร:
shuffle()
วิธีการสุ่มแบบสุ่มจะเป็นการสับรายการในคอลเลคชั่น:
$collection = collect([1, 2, 3, 4, 5]);
$shuffled = $collection->shuffle();
$shuffled->all();
// [3, 2, 5, 1, 4] - (generated randomly)
ในแบบจำลองของคุณให้เพิ่มสิ่งนี้:
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)
ฉันมีตารางที่มีหลายพันระเบียนดังนั้นฉันต้องการบางสิ่งที่รวดเร็ว นี่คือรหัสของฉันสำหรับแถวสุ่มหลอก:
// 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
แรกเท่านั้นที่จะถูกเรียกคืนและดังนั้นจึงมีแนวโน้มที่จะถูกเรียกคืนมากกว่าแถวอื่น ๆ