Rails, ActiveRecord, request identifier in int array, keep order of passed array

I think of the best solution to the problem. Let's say that we have a list of ActiveRecord model identifiers:

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

Then I would like to make a query that selects all users, for example, with identifiers from the list, but to maintain order. If i do

 User.where(id: ids) 

the answer will be a list of users with asc order by id, but I want the order to be the same as in the array.

What do you think is the best solution here? Select all users and then manage the list of ActiveRecord objects? There may be a smarter way to do this.

Thanks!

+11
source share
6 answers

As for here , for postgresql,

 User.where(id: ids).order("position(id::text in '#{ids.join(',')}')") 
+7
source

If you use MySQL, you can use FIELD to organize the results:

 class User < ActiveRecord::Base def self.find_in_order(ids) self.where(id: ids).order("FIELD(id, #{ids.join(',')})") end end User.find_in_order([1, 100, 5, 30, 4, 2, 88, 44]) 
+6
source

consider MySQL and Postgresql less , if you have a small identifier size,

 User.where(id: ids).sort_by { |u| ids.index(u.id) } 
+4
source

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 must first run the module

 CREATE EXTENSION intarray 
+1
source
 users_by_id = User.find(ids).index_by(&:id) # Gives you a hash indexed by ID ids.collect {|id| users_by_id[id] } 
0
source

Another feature 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') 

Please note that order is very important.

Solution based on fooobar.com/questions/61830 / ...

0
source

Source: https://habr.com/ru/post/983903/


All Articles