Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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]

Then I would like to make query that selects all users for example with ids from the list but to keep the order. If I do

User.where(id: ids)

the response 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 that it's the best solution here? Select all users and then to manipulate the list of ActiveRecord objects? Maybe there is a more clever way to do that.

Thanks!

like image 364
user1107922 Avatar asked Mar 17 '15 10:03

user1107922


5 Answers

With reference to here, for postgresql,

User.where(id: ids).order("position(id::text in '#{ids.join(',')}')")
like image 112
Vic Avatar answered Nov 10 '22 11:11

Vic


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) }
like image 12
fengd Avatar answered Nov 10 '22 13:11

fengd


If you are using MySQL, you can use FIELD to order 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])
like image 10
BroiSatse Avatar answered Nov 10 '22 11:11

BroiSatse


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
like image 1
lx00st Avatar answered Nov 10 '22 11:11

lx00st


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

like image 1
mtc Avatar answered Nov 10 '22 12:11

mtc