Rails, ActiveRecord, query id in array of ints, keep order of passed array

后端 未结 7 1816
粉色の甜心
粉色の甜心 2021-02-01 05:38

I am thinking about the best solution for a problem. Let\'s say that we have a list of ids of ActiveRecord model:

ids = [1, 100, 5, 30, 4, 2, 88, 44]


        
相关标签:
7条回答
  • 2021-02-01 05:59

    Another possibility for Postgres (9.4 or later):

    ordered_ids = [1, 100, 5, 30, 4, 2, 88, 44]
    User.joins("join unnest('{#{ordered_ids.join(',')}}'::int[]) WITH " \
               "ORDINALITY t(id, ord) USING (id)").reorder('t.ord')
    

    Notice that the reorder is extremely important.

    Solution based on https://stackoverflow.com/a/35456954

    0 讨论(0)
  • 2021-02-01 06:00

    regard less of MySQL and Postgresql, if you have a small size of ids,

    User.where(id: ids).sort_by { |u| ids.index(u.id) }
    
    0 讨论(0)
  • 2021-02-01 06:14

    With reference to here, for postgresql,

    User.where(id: ids).order("position(id::text in '#{ids.join(',')}')")
    
    0 讨论(0)
  • 2021-02-01 06:14

    if you want to get a result of Model::ActiveRecord_Relation

    order(Arel.sql("field(id, ids.join(', ') asc"))
    

    Arel.sql is required to prevent the message in log:

    Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s)

    0 讨论(0)
  • 2021-02-01 06:15
    users_by_id = User.find(ids).index_by(&:id) # Gives you a hash indexed by ID
    ids.collect {|id| users_by_id[id] }
    
    0 讨论(0)
  • 2021-02-01 06:18

    If you are using Postgres you can use intarray

    class User < ActiveRecord::Base
      def self.find_in_order(ids)
        self.where(id: ids).order("idx(array[#{ids.join(',')}], id)")
      end
    end
    

    you should init module first

    CREATE EXTENSION intarray
    
    0 讨论(0)
提交回复
热议问题