我有一组id,存储在一些外部存储(rails cache或redis)中。在控制器的操作中,我获取此数据并使用它选择对象,即
ids = [5, 1, 17, 84] # really fetched from external source
result = MyModel.where(:id => ids)
我还希望它与array_of ids中的ID一样有序:
ids == result.map(&:id) # => true
作为解决方法,我使用mysql FIELD函数排序:
MyModel.where(:id => ids).order("FIELD(id, #{ids.join ', '})")
但我不喜欢这种方法,因为它是特定于mysql的,并且在大ids
数组的情况下会创建非常长的查询。
有没有更好的,与DB无关的方法呢?从数据库获取未分类的数据并在ruby端进行排序是不可取的,因为它资源昂贵并且难以使用分页。
感谢。
答案 0 :(得分:12)
我刚刚发布了一个gem(order_as_specified),允许你像这样进行原生SQL排序:
MyModel.where(id: ids).order_as_specified(id: ids)
它返回一个ActiveRecord关系,因此可以与其他方法链接:
MyModel.where(id: ids).order_as_specified(id: ids).limit(3)
如果你有点好奇,那就是它的构建:
... ORDER BY ID='5' DESC, ID='1' DESC, ID='17' DESC, ID='84' DESC
答案 1 :(得分:5)
如果您不介意接收数组而不是ActiveRecord Collection,则可以使用:
result = MyModel.find(ids).sort_by {|m| ids.index(m.id)}
答案 2 :(得分:0)
如果数组的顺序始终相同,您可以将缓存的订单列添加到数据库表中。
MyModel.order(" cached_order&#34)