Laravel-красноречивый или беглый случайный ряд


Как я могу выбрать случайную строку, используя Eloquent или Fluent в Laravel framework?

Я знаю, что с помощью SQL, вы можете сделать заказ по RAND(). Однако, я хотел бы получить случайную строку без выполнение подсчета количества записей до первоначального запроса.

какие идеи?

10 152

10 ответов:

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

Регистрация в этой статье на случайных строках MySQL. Laravel 5.2 поддерживает это, для более старой версии, нет лучшего решения, чем использование необработанные запросы.

edit 1: как упоминалось Double Gras, orderBy() не позволяет ничего другого, кроме ASC или DESC так как этой изменить. Я обновил свой ответ соответственно.

edit 2: что Laravel 5.2, наконец, реализует функции-оболочки для этого. Это называется inRandomOrder ().

это работает нормально,

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

вы также можете изменить аргумент в случайной функции, чтобы получить более одной записи.

Примечание: не рекомендуется, если у вас есть огромные данные, как это будет получать все строки, а затем возвращает случайное значение.

tl; dr: в настоящее время он реализован в Laravel, см. "edit 3" ниже.


к сожалению, на сегодняшний день есть некоторые предостережения с ->orderBy(DB::raw('RAND()')) предлагаемое решение:

  • это не ДБ-агностик. например, SQLite и PostgreSQL используют RANDOM()
  • еще хуже, это решение не применимо, так этот изменить:

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


edit: теперь вы можете использовать orderByRaw () способ: ->orderByRaw('RAND()'). Однако это все еще не ДБ-агностик.

FWIW, CodeIgniter реализует специальный RANDOM направление сортировки, которое заменяется правильной грамматике при построении запроса. Также это, кажется, довольно легко осуществить. Похоже, у нас есть кандидат на улучшение Laravel:)

обновление: вот это вопрос об этом на GitHub, и мое ожидание pull-запрос.


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


edit 3: наконец-то! Начиная С Laravel 5.2.33 (изменений,PR #13642) вы можете использовать собственный метод inRandomOrder():

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

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

на Laravel 4 и 5 the order_by заменить на orderBy

Итак, должно быть:

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

вы также можете использовать метод order_by с свободно и красноречиво, как:

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

Это немного странно, но работает.

Edit: как сказал @Alex, это использование чище, а также работает:

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

Для Laravel 5.2 >=

используйте красноречивый метод:

inRandomOrder()

метод inRandomOrder может использоваться для случайной сортировки результатов запроса. Например, вы можете использовать этот метод для извлечения случайного пользователя:

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

из документов: https://laravel.com/docs/5.2/queries#ordering-grouping-limit-and-offset

вы можете использовать:

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

в вашей модели добавить это:

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()') Что делает то же самое, u может затем цепь ->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();