【问题标题】:Does ActiveRecord find_all_by_X preserve order? If not, what should be used instead?ActiveRecord find_all_by_X 是否保留顺序?如果不是,应该改用什么?
【发布时间】:2012-04-19 17:10:54
【问题描述】:

假设我有一个非空数组 idsThing 对象 ID,我想使用 things = Thing.find_all_by_id(ids) 查找相应的对象。我的印象是things 不一定有类似于ids 的排序。

  1. 我的印象正确吗?

  2. 如果是这样,我可以使用什么来代替 find_all_by_id 来保持顺序并且不会不必要地多次访问数据库?

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:
    1. 是的
    2. 使用Array#sort

    检查一下:

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

    where(:id =&gt; ids) 将使用IN() 生成查询。然后排序!方法将遍历查询结果并比较 id 在 ids 数组中的位置。

    【讨论】:

    • 我曾考虑过这种方法,但似乎有点迂回。我愿意相信这是最好的方法,但至少不会编写我自己的 SQL 查询。
    • 我不是 SQL 专家,但我很确定您只能以升序或降序的方式进行排序,您的排序目标更加随意。 Ruby 的排序方法应该非常高效。
    【解决方案2】:

    @tybro0103 的答案会起作用,但对于大量 N id 来说效率很低。特别是,Array#index 在 N 中是线性的。散列对于较大的 N 效果更好,如

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

    您甚至可以使用这种技术根据任何不必要的唯一属性进行任意排序,如

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

    find_all_by_id 在 rails 4 中被弃用,这就是我在这里使用 where 的原因,但行为是相同的。

    【讨论】:

      猜你喜欢
      • 2011-05-13
      • 1970-01-01
      • 2019-08-25
      • 1970-01-01
      • 2013-02-28
      • 2014-06-12
      • 2010-10-14
      • 2017-03-04
      • 1970-01-01
      相关资源
      最近更新 更多