現在、私は次のことを行っています:
responses = Response.where(user_id: current_user.uid)
qids = []
responses.each { |r| qids << r._id}
return qids
これを行うより良い方法はありますか?
.only()
より少ないデータを取得するために使用します。
quids = Response.only(:_id).where(user_id: current_user.uid).map(&:_id)
結果セット内で一意の ID などを取得する場合は、distinct メソッドを使用するのと機能的に同等です。そうすれば、マッピング操作を保存でき、はるかに高速に見えるようになります (テストと、少し注意してテストを行う必要がある理由については、下部に説明があります)。
Response.where(user_id: current_user.uid).distinct(:_id)
したがって、一意ではないものを取得したい場合や、何らかの理由で重複した結果を取得したい場合にのみ、これを使用してください。つまり、あなたの応答がいいね! される可能性があり、すべてのいいね! の配列を取得したい場合 (たとえば、いいねに関する統計を計算したいとします):
Response.where(user_id: current_user.uid).map { |r| r.likes }
これはいくつかのランダムなテストですが、より信頼できる結果を得るには、アクションを繰り返すのではなく、大規模なデータベースでテストをコミットする必要があります。私が知っている限りでは、同じクエリを何度も繰り返すためのあらゆる種類の最適化が存在する可能性があることを意味します (明らかに、マップにはそのような最適化を含めることはできません)。
Benchmark.measure { 1000.times { Organization.where(:event_labels.ne =[]).map(&:_id) } }
=> 6.320000 0.290000 6.610000 ( 6.871498)
Benchmark.measure { 1000.times { Organization.where(:event_labels.ne => []).only(:_id).map(&:_id) } }
=> 5.490000 0.140000 5.630000 ( 5.981122)
Benchmark.measure { 1000.times { Organization.where(:event_labels.ne => []).distinct(:_id) } }
=> 0.570000 0.020000 0.590000 ( 0.773239)
Benchmark.measure { 1000.times { Organization.where(:event_labels.ne => []).only(:_id) } }
=> 0.140000 0.000000 0.140000 ( 0.141278)
Benchmark.measure { 1000.times { Organization.where(:event_labels.ne => []) } }
=> 0.070000 0.000000 0.070000 ( 0.069482)
なしでは少し時間map
がonly
かかるため、使用するonly
と便利です。実際に使用しないと少しパフォーマンスmap
が低下するように見えますが、データが少ないとmap
実行が少し速くなるようです。とにかく、このテストによると、すべてのメトリック (ユーザー、システム、合計、実数) で、 andコンボdistinct
を使用するよりも約 10 倍速いようですが、なしで使用するよりは遅くなります。only
map
only
map
Response.where(user_id: current_user.uid).map { |r| r._id }
それはもう少し慣用的です。
mongoid に関する限り、mongoid が提供する唯一の「マッピング」タイプの機能は、カスタム map-reduce フィルターです。ドキュメントをチェックアウトできます。
この場合、そのようなフィルターを作成してもメリットはありません。データセット全体を読み込んでおり (遅延読み込みは役に立ちません)、何も削減していません。