Laravel-웅변 또는 유창한 임의 행


242

Laravel 프레임 워크에서 Eloquent 또는 Fluent를 사용하여 임의의 행을 선택하려면 어떻게해야합니까?

SQL을 사용하면 RAND ()로 주문할 수 있다는 것을 알고 있습니다. 그러나 초기 쿼리 이전의 레코드 수를 계산 하지 않고 임의의 행을 얻고 싶습니다 .

어떤 아이디어?


최소한 두 개의 쿼리를 실행하지 않고이 작업을 수행하는 가장 좋은 방법은 없습니다.
NARKOZ

답변:


586

라 라벨> = 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 무작위 행에서 확인하십시오 . Laravel 5.2는이를 지원합니다. 이전 버전의 경우 RAW 쿼리 를 사용하는 것보다 더 나은 솔루션은 없습니다 .

편집 1 : Double Gras가 언급했듯이 orderBy ()는 변경 이후 ASC 또는 DESC 이외의 다른 것을 허용하지 않습니다 . 이에 따라 답변을 업데이트했습니다.

편집 2 : Laravel 5.2는 마침내 이것을 위해 래퍼 기능 을 구현 합니다 . inRandomOrder () 라고 합니다.


81
단일 행을 원하면 'get'을 'first'로 바꾸십시오.
Collin Price

14
PostgreSQL 사용'RANDOM()'
dwenaus

2
경고 : 큰 데이터 세트에서이 속도는 매우 느려서 약 900ms가 추가되었습니다.
S ..

3
이것을 페이지 매길 수 있습니까?
Irfandi D. Vendy

3
그러나 모든 새 페이지에서 정렬이 임의적입니다. F5를 누르는 것과 본질적으로 동일하기 때문에 의미가 없습니다.
aebersold

49

이것은 잘 작동합니다.

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

임의 함수에서 인수를 변경하여 둘 이상의 레코드를 얻을 수도 있습니다.

참고 : 대량의 데이터가 있으면 모든 행을 먼저 가져온 다음 임의의 값을 반환하므로 권장하지 않습니다.


61
성능 측면에서 단점은 모든 레코드가 검색된다는 것입니다.
Gras Double

3
여기서 무작위는 SQL 쿼리가 아닌 컬렉션 객체에서 호출됩니다. 임의의 함수는 PHP 측에서 실행됩니다
astroanu

@astroanu 맞습니다. 그러나 해당 컬렉션을 채우려면 모든 행이 쿼리됩니다.
MetalFrog

1
나는 틀릴 수 있지만 무작위 함수에 전달 된 매개 변수가 컬렉션의 크기와 같을 때 작동하지 않는 것 같습니다.
Brynn Bateman

이것은 좋지 않습니다 ... 이렇게하면 모든 레코드를 검색하고 임의의 레코드를 가져옵니다. 테이블에 레코드가 너무 많으면 앱에 좋지 않을 수 있습니다.
앤더슨 실바

34

tl; dr : 요즘은 라 라벨에 구현되어 있습니다. 아래의 "편집 3"을보십시오.


안타깝게도 오늘 현재 ->orderBy(DB::raw('RAND()'))제안 된 솔루션에 대한 몇 가지주의 사항이 있습니다.

  • DB에 구애받지 않습니다. 예 : SQLite 및 PostgreSQL 사용RANDOM()
  • 더 나쁜 것은 이 변경 이후이 솔루션은 더 이상 적용되지 않습니다 .

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


편집 : 이제 orderByRaw () 메소드를 사용할 수 있습니다 :->orderByRaw('RAND()') . 그러나 이것은 여전히 ​​DB에 구애받지 않습니다.

FWIW, CodeIgniter는 특별한 구현 RANDOM 정렬 방향을 쿼리를 작성할 때 올바른 문법으로 대체됩니다. 또한 구현하기가 상당히 쉬운 것 같습니다. 라 라벨 개선 후보가있는 것 같습니다 :)

업데이트 : 여기 GitHub 의 문제 와 보류중인 pull 요청이 있습니다.


편집 2 : 체이스를 잘라 봅시다. 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();

그것은 앞으로 호환 그래서 당신은 inRandomOrder에 5.1 매크로 이름을 변경해야합니다) 자세한 사항 :
샌더 프랜트

5.1 프로젝트를 5.2로 마이그레이션하기 전에 5.1 프로젝트를 준비하는 동안 정확히 한 가지입니다.
Gras Double

이것은 훌륭한 답변입니다. 내가 대답을 좋아할 수 있다면 나는 할 것이다!
mwallisch

18

에서는 Laravel 4 및 5order_by로 대체orderBy

따라서 다음과 같아야합니다.

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

사용자 :: orderBy (DB :: raw ( 'RAND ()'))-> get ();
다리우스

1
감사하지만 작동하는 방법에 대한 정보를 줄 수 있습니까?
alayli

좀 더 구체적으로 할 수 있습니까? 어떤 종류의 정보?
Teodor Talov


9

라 라벨 5.2의 경우> =

Eloquent 방법을 사용하십시오 :

inRandomOrder()

inRandomOrder 메소드는 쿼리 결과를 무작위로 정렬하는 데 사용될 수 있습니다. 예를 들어,이 방법을 사용하여 임의의 사용자를 가져올 수 있습니다.

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

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


과정 :: inRandomOrder ()-> take (20)-> get (); 나를 위해 작동하지 않습니다-Find.php 줄 219의 잘못된 정렬 사양
MJ

1
모델 공장 또는 DB 파종 유용이 하나의
살레 마흐무드

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
이것은 잘 작동하고 조금 더 깨끗합니다
..-


3

이 명령을 쉽게 사용할 수 있습니다.

// 질문 : 모델 이름
// DB 셔플 레코드에서 10 개의 행을 가져옵니다 ...

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

3

먼저 지정하거나 실패하는 것을 선호합니다.

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

3

Laravel에는 결과 순서를 섞는 내장 방법이 있습니다.

다음은 설명서에서 인용 한 것입니다.

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

이것의 문제는 id $count가 첫 번째 보다 큰 행이 여러 개있는 경우 검색 할 수 있으므로 다른 행보다 검색 할 가능성이 높다는 것입니다.
kemika
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.