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

167

Как выбрать случайную строку с использованием "Красноречивого" или "Свободного" в рамках Laravel?

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

Любые идеи?

  • 0
    Нет лучшего способа сделать это, не выполнив хотя бы два запроса.
Теги:
eloquent
fluent

12 ответов

416
Лучший ответ

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

  • 68
    Замените «get» на «first», если вы хотите одну строку.
  • 12
    для PostgreSQL используйте 'RANDOM()'
Показать ещё 6 комментариев
39

Это работает отлично,

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

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

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

  • 47
    Недостатком в производительности является то, что все записи извлекаются.
  • 2
    здесь случайный объект вызывается для объекта коллекции, а не для запроса SQL. случайная функция запускается на стороне PHP
Показать ещё 4 комментария
26

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


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

  • Это не DB-агностик. например, SQLite и PostgreSQL используют 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();
  • 1
    Спасибо, второе редактирование - действительно лучший ответ!
  • 1
    Теперь вы можете взглянуть на 3-е редактирование;)
Показать ещё 2 комментария
15

В Laravel 4 и 5 order_by заменяется на orderBy

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

User::orderBy(DB::raw('RAND()'))->get();
  • 0
    Пользователь :: OrderBy (DB :: сырец ( 'RAND ()')) -> получить ();
  • 1
    Это работает, спасибо, но не могли бы вы дать некоторую информацию, как это работает?
Показать ещё 2 комментария
10

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

ModelName::inRandomOrder()->first();
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
    это работает также и немного чище .. -> order_by (\ DB :: raw ('RAND ()'))
7

Для Laravel 5.2 > =

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

inRandomOrder()

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

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

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

  • 0
    Курс :: inRandomOrder () -> взять (20) -> Get (); У меня не работает - плохая сортировка в строке Find.php 219
  • 1
    Это полезно для модельных фабрик или посева БД
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()') который делает то же самое, затем вы можете whereRaw('RAND()') цепочку ->get() или ->first() или даже сойти с ума и добавить ->paginate(int).

1

Вы можете легко использовать эту команду:

//Вопрос: название модели
// берем 10 строк из БД в случайных записях...

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

У меня есть таблица с тысячами записей, поэтому мне нужно что-то быстро. Это мой код для псевдослучайной строки:

// 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(); 
  • 0
    Проблема в том, что если есть несколько строк с идентификаторами, превышающими $count будет извлечена только первая из них, и поэтому она также будет с большей вероятностью получена, чем любая другая строка.
0

Используйте функцию Laravel

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню