Подтвердить что ты не робот

Что такое "Rails 4 Way" для поиска некоторого количества случайных записей?

User.find(:all, :order => "RANDOM()", :limit => 10) был тем, как я это делал в Rails 3.

User.all(:order => "RANDOM()", :limit => 10) - это то, как я думал, что Rails 4 сделает это, но это все еще дает мне предупреждение об отказе:

DEPRECATION WARNING: Relation#all is deprecated. If you want to eager-load a relation, you can call #load (e.g. `Post.where(published: true).load`). If you want to get an array of records from a relation, you can call #to_a (e.g. `Post.where(published: true).to_a`).
4b9b3361

Ответ 1

Вместо этого вы захотите использовать методы order и limit. Вы можете избавиться от all.

Для PostgreSQL и SQLite:

User.order("RANDOM()").limit(10)

Или для MySQL:

User.order("RAND()").limit(10)

Ответ 2

Поскольку случайная функция может меняться для разных баз данных, я бы рекомендовал использовать следующий код:

User.offset(rand(User.count)).first

Конечно, это полезно, только если вы ищете только одну запись.

Если вы хотите получить больше этого, вы можете сделать что-то вроде:

User.offset(rand(User.count) - 10).limit(10)

- 10 должен гарантировать, что вы получите 10 записей в случае, когда rand возвращает число больше, чем count - 10.

Помните, что вы всегда будете получать 10 последовательных записей.

Ответ 3

Я думаю, что лучшее решение действительно упорядочивается случайным образом в базе данных. Но если вам нужно избегать конкретной случайной функции из базы данных, вы можете использовать подход pluck и shuffle.

Для одной записи:

User.find(User.pluck(:id).shuffle.first)

Для более чем одной записи:

User.where(id: User.pluck(:id).sample(10))

Ответ 4

Я бы предложил сделать эту область видимости, как вы можете ее потом:

class User < ActiveRecord::Base
  scope :random, -> { order(Arel::Nodes::NamedFunction.new('RANDOM', [])) }
end 

User.random.limit(10)
User.active.random.limit(10)

Ответ 5

Хотя это не самое быстрое решение, мне нравится краткость:

User.ids.sample(10)

Метод .ids дает массив идентификаторов пользователя, а .sample(10) выбирает 10 случайных значений из этого массива.

Ответ 6

Для MYSQL это сработало для меня:

User.order("RAND()").limit(10)

Ответ 7

Здесь быстрое решение. В настоящее время он использует его с более чем 1,5 миллионами записей и получает достойную производительность. Лучшим решением было бы кэшировать один или несколько наборов случайных записей, а затем обновлять их с помощью рабочего стола в нужном интервале.

Создан random_records_helper.rb файл:

module RandomRecordsHelper

 def random_user_ids(n)
    user_ids = []
    user_count = User.count
    n.times{user_ids << rand(1..user_count)}
    return user_ids
 end

в контроллере:

@users = User.where(id: random_user_ids(10))

Это намного быстрее, чем метод .order("RANDOM()").limit(10) - я перешел с 13-секундного времени загрузки до 500 мс.