例如我把一个千辛万苦排序出来的 ids 数组,重托给 where 去查询。结果 where 这小婊砸不按 ids 数组里的顺序乖乖查,按 id 的升序去查的。
ids = [ 3,2,1]
A.where(ids).map(&:id)
=> [1,2,3]
诸君有没有遇到类似问题,是如何解决的?
其实我想说的是,多写两行代码可以解决问题的
ids = [3, 2, 1]
hash = {}
ids.each {|id| hash[id] = nil}
A.where(ids).each {|a| hash[a.id] = a}
hash.values # 这里就是按照 ids 排序的 A,id 不存在的话是 nil
我遇到的一个问题跟你的类似:
user_names = ['steve', 'bob', 'cook']
User.where(name: user_names).sort_by { |user| user_names.index(user.name) }
#14 楼 @gonglexin 用 7 楼和 13 楼里提到的方法可以解决,sort_by 后会变成数组,因为后面还有分页需要调用,还需要最后是 relation 对象
#16 楼 @gihnius 下班了,找了一堆解决方案:Ordering a query result set by an arbitrary list in PostgreSQL Raw,缺点是都要写 sql.
这不是 where
的锅~ MySQL 下可以用 filed 来解决
module Extensions::ActiveRecord::FindByOrderedIds
extend ActiveSupport::Concern
module ClassMethods
def find_ordered(ids, table_name)
return where(id: ids) unless ids.present?
sanitized_id_string = ids.map {|id| connection.quote(id)}.join(',')
where(id: ids).order("FIELD(#{table_name}.id, #{sanitized_id_string})")
end
end
end
ActiveRecord::Base.include(Extensions::ActiveRecord::FindByOrderedIds)
A.find_ordered([3, 1,2,5])
就会按顺序查出来了。
#20 楼 @42thcoder 我找到的也是这段代码,忘了在哪里找到的了? 另外,不明白的是为啥要去 connection.quote 一下 id?直接操作传进来的 id 不行么