Как выбрать случайную строку с использованием "Красноречивого" или "Свободного" в рамках Laravel?
Я знаю, что с помощью SQL вы можете сделать заказ с помощью RAND(). Тем не менее, я хотел бы получить случайную строку без, выполняющую подсчет количества записей перед исходным запросом.
Любые идеи?
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 поддерживает это, для более старой версии нет лучшего решения, а затем RAW-запросов.
edit 1: Как уже упоминалось Double Gras, orderBy() не позволяет ничего другого, кроме ASC или DESC, поскольку this изменяется. Я соответствующим образом обновил свой ответ.
edit 2: Laravel 5.2, наконец, реализует функцию обертки для этого. Он назывался inRandomOrder().
'RANDOM()'
Это работает отлично,
$model=Model::all()->random(1);
вы также можете изменить аргумент в случайной функции, чтобы получить более одной записи.
Примечание: не рекомендуется, если у вас есть огромные данные, так как это сначала выберет все строки, а затем вернет случайное значение.
tl; dr: В настоящее время он реализован в Laravel, см. "edit 3" ниже.
К сожалению, на сегодняшний день есть некоторые оговорки с предложенным решением ->orderBy(DB::raw('RAND()'))
:
RANDOM()
Хуже того, это решение больше не применимо после этого изменения:
$direction = strtolower($direction) == 'asc'? 'asc': 'desc';
редактировать: теперь вы можете использовать метод orderByRaw(): ->orderByRaw('RAND()')
. Однако это все еще не DB-агностик.
Кстати, CodeIgniter реализует специальное RANDOM
направление сортировки, которое заменяется правильной грамматикой при построении запроса. Также это кажется довольно простым для реализации. Похоже, у нас есть кандидат на улучшение Laravel :)
обновление: вот проблема об этом на GitHub, и мой ожидающий запрос на извлечение.
редактировать 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();
В Laravel 4 и 5 order_by
заменяется на orderBy
Итак, это должно быть:
User::orderBy(DB::raw('RAND()'))->get();
Вы можете использовать:
ModelName::inRandomOrder()->first();
Вы также можете использовать метод order_by с беглостью и красноречием, например:
Posts::where_status(1)->order_by(DB::raw(''),DB::raw('RAND()'));
Это немного странное использование, но работает.
Изменить: Как сказал @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
В вашей модели добавьте следующее:
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()')
который делает то же самое, затем вы можете whereRaw('RAND()')
цепочку ->get()
или ->first()
или даже сойти с ума и добавить ->paginate(int)
.
Вы можете легко использовать эту команду:
//Вопрос: название модели
// берем 10 строк из БД в случайных записях...
$questions = Question::orderByRaw('RAND()')->take(10)->get();
У меня есть таблица с тысячами записей, поэтому мне нужно что-то быстро. Это мой код для псевдослучайной строки:
// 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
будет извлечена только первая из них, и поэтому она также будет с большей вероятностью получена, чем любая другая строка.
Используйте функцию Laravel
ModelName::inRandomOrder()->first();