Does ActiveRecord find_all_by_X preserve order? If not, what should be used instead?

别说谁变了你拦得住时间么 提交于 2019-12-07 17:26:54

问题


Suppose I have a non-empty array ids of Thing object ids and I want to find the corresponding objects using things = Thing.find_all_by_id(ids). My impression is that things will not necessarily have an ordering analogous to that of ids.

  1. Is my impression correct?

  2. If so, what can I used instead of find_all_by_id that preserves order and doesn't hit the database unnecessarily many times?


回答1:


  1. Yes
  2. Use Array#sort

Check it out:

Thing.where(:id => ids).sort! {|a, b| ids.index(a.id) <=> ids.index(b.id)}

where(:id => ids) will generate a query using an IN(). Then the sort! method will iterate through the query results and compare the positions of the id's in the ids array.




回答2:


@tybro0103's answer will work, but gets inefficient for a large N of ids. In particular, Array#index is linear in N. Hashing works better for large N, as in

by_id = Hash[Thing.where(:id => ids).map{|thing| [thing.id, thing]}]
ids.map{|i| by_id[i]}

You can even use this technique to arbitrarily sort by any not-necessarily unique attribute, as in

by_att = Thing.where(:att => atts).group_by(&:att)
atts.flat_map{|a| by_att[a]}

find_all_by_id is deprecated in rails 4, which is why I use where here, but the behavior is the same.



来源:https://stackoverflow.com/questions/10037460/does-activerecord-find-all-by-x-preserve-order-if-not-what-should-be-used-inst

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!