---

こんにちは〜

【Rails】sampleでランダムな要素を取得する

sampleについて↓
https://ref.xaio.jp/ruby/classes/array/sample
今日見たソースコードで↓のようなのがあった。

user_ids = []
5.times { user_ids << User.where(status: :active).sample.id }

​これを実行すると、5回分ユーザーを全件取ってきてランダムな要素を返す。
5回もSQL発行してるので重くなる。
(5回ならまだいいけど、数が増えるとめちゃくちゃ重くなる)

[15] pry(main)> user_ids = []
=> []
[16] pry(main)> 5.times { user_ids << User.where(status: :active).sample.id }
  User Load (0.8ms)  SELECT `users`.* FROM `users` WHERE `users`.`status` = 2
  User Load (1.3ms)  SELECT `users`.* FROM `users` WHERE `users`.`status` = 2
  User Load (1.8ms)  SELECT `users`.* FROM `users` WHERE `users`.`status` = 2
  User Load (2.3ms)  SELECT `users`.* FROM `users` WHERE `users`.`status` = 2
  User Load (2.0ms)  SELECT `users`.* FROM `users` WHERE `users`.`status` = 2
=> 5

どうしたらいいか

sampleは個数を指定できるし、idだけが必要ならidだけを取ってきてsampleした方がいい。

user_ids = []
User.where(status: :active).pluck(:id).sample(5)

#実行結果↓
[17] pry(main)> user_ids = []
=> []
[18] pry(main)> User.where(status: :active).pluck(:id).sample(5)
   (0.4ms)  SELECT `users`.`id` FROM `users` WHERE `users`.`status` = 2

​ 上記にすれば、SQLを発行するのは1回で済む。 ​

備考

https://easyramble.com/get-record-randomly-with-active-record.html
​ ランダムにレコードを取得するやり方を比較してくれている記事があった。