Rails中使用.where查询id数组对应记录时如何保持原id数组顺序
解决方案
根据你使用的Rails版本和数据量大小,可选择以下任意一种方案实现需求,所有方案均已兼容id字符串转整数的要求:
方案1:Rails 7+ 原生方案(推荐)
Rails 7及以上版本内置in_order_of方法,无需额外编写SQL片段,无SQL注入风险:
ids = ["4", "15", "10", "20", "1"] # 先将字符串id转为整数适配数据库字段类型 int_ids = ids.map(&:to_i) stores = Store.published.where(id: int_ids).in_order_of(:id, int_ids)
方案2:低版本Rails 数据库层面排序(适合大数据量)
性能优于内存排序,根据你使用的数据库类型选择对应写法:
- MySQL/MariaDB 版本
ids = ["4", "15", "10", "20", "1"] int_ids = ids.map(&:to_i) stores = Store.published.where(id: int_ids) .order(Arel.sql("FIELD(id, #{int_ids.join(',')})"))
- PostgreSQL 版本
ids = ["4", "15", "10", "20", "1"] int_ids = ids.map(&:to_i) order_clause = int_ids.map.with_index { |id, idx| "WHEN #{id} THEN #{idx}" }.join(' ') stores = Store.published.where(id: int_ids) .order(Arel.sql("CASE id #{order_clause} END"))
方案3:内存层面排序(兼容所有环境,适合小数据量)
无需关注数据库类型,写法最简单,适合查询数据量在100条以内的场景:
ids = ["4", "15", "10", "20", "1"] int_ids = ids.map(&:to_i) stores = Store.published.where(id: int_ids).sort_by { |store| int_ids.index(store.id) }
注意:上述所有方案都会自动过滤掉不存在的id对应的记录,不会影响剩余有效记录的排序顺序。
内容的提问来源于stack exchange,提问作者Doolan
相关产品推荐
相关产品推荐

