User.find(:all, :order => "RANDOM()", :limit => 10)
était comme je l’ai fait dans Rails 3.
User.all(:order => "RANDOM()", :limit => 10)
est ainsi que je pensais que Rails 4 le ferait, mais cela me donne toujours un avertissement pour obsolescence:
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`).
Vous préférerez utiliser les méthodes order
et limit
. Vous pouvez vous débarrasser de la all
.
Pour PostgreSQL et SQLite:
User.order("RANDOM()").limit(10)
Ou pour MySQL:
User.order("Rand()").limit(10)
Comme la fonction aléatoire pourrait changer pour différentes bases de données, je vous recommande d'utiliser le code suivant:
User.offset(Rand(User.count)).first
Bien sûr, cela n’est utile que si vous recherchez un seul enregistrement.
Si vous voulez en avoir plus d'un, vous pouvez faire quelque chose comme:
User.offset(Rand(User.count) - 10).limit(10)
Le - 10
vous assure d'obtenir 10 enregistrements au cas où Rand renvoie un nombre supérieur à compte - 10 .
Gardez à l'esprit que vous obtiendrez toujours 10 enregistrements consécutifs.
Je pense que la meilleure solution consiste à commander de manière aléatoire dans la base de données . Mais si vous devez éviter une fonction aléatoire spécifique de la base de données, vous pouvez utiliser l'approche pluck
et shuffle
.
Pour un enregistrement:
User.find(User.pluck(:id).shuffle.first)
Pour plus d'un enregistrement:
User.where(id: User.pluck(:id).sample(10))
Je suggèrerais d'en faire une portée car vous pouvez ensuite l'enchaîner:
class User < ActiveRecord::Base
scope :random, -> { order(Arel::Nodes::NamedFunction.new('RANDOM', [])) }
end
User.random.limit(10)
User.active.random.limit(10)
Pour MYSQL, cela a fonctionné pour moi:
User.order("Rand()").limit(10)
Recommandez vivement cette gemme pour les enregistrements aléatoires, spécialement conçue pour les tables avec beaucoup de lignes de données:
https://github.com/haopingfan/quick_random_records
Toutes les autres réponses fonctionnent mal avec une base de données volumineuse, à l'exception de cette gemme:
4.6ms
totalement.User.order('Rand()').limit(10)
a coûté 733.0ms
.offset
a coûté 245.4ms
totalement.User.all.sample(10)
coût 573.4ms
.Remarque: Ma table ne compte que 120 000 utilisateurs. Plus vous avez de disques, plus la différence de performance sera énorme.
METTRE À JOUR:
Effectuer sur une table avec 550 000 lignes
Model.where(id: Model.pluck(:id).sample(10))
coût 1384.0ms
gem: quick_random_records
ne coûte que 6.4ms
totalementVous pouvez appeler .sample
sur les enregistrements, par exemple: User.all.sample(10)