简体   繁体   中英

Rails Sorting the record based on the array passed in where condition

I want to sort my where condition result in the order i am passing the values in array . what i am doing is i have an array of ids

ids = [80, 20, 3, 91, 84, 90, 98, 97, 68, 99, 92, 73]

When i am passing this array to where condition like :

products = Product.where(id: ids)

its returning the result active record relation in different order (random order)something like :

=>[ 20 ,84, 3,98 , .............. ] 

(this is active record relation object i have mention only ids here )

But i want it to return the object in same order i am passing the the values like (In active record relation object not an array)

=> [80, 20, 3, 91, 84, 90, 98, 97, 68, 99, 92, 73]

How can i do this .

I have got the solution of this just need to do

In product model inside product.rb file put :

 def self.order_by_ids(ids)
    order_by = ["case"]
    ids.each_with_index.map do |id, index|
      order_by << "WHEN id='#{id}' THEN #{index}"
    end
    order_by << "end"
    order(order_by.join(" "))
  end

And query will be :

products = Product.where(:id => ids).order_by_ids(ids)

Here ids will be array of id's

Simply sort by using indices of your ids array:

products = Product.where(id: ids).sort_by { |prod| ids.index(prod.id) }

Plus it's database agnostic, and it's ok to do in Ruby as you won't have millions of ids in any case.

The answer is for mysql only

There is a function in mysql called FIELD()

So you can do something like

products = Product.where(id: ids).order("field(id, #{ids.join ','})")

In Postgres

hot_offer_ids = ["7081", "7083", "6917", "5075"]
values = ''
hot_offer_ids.each_with_index do |offer_id, index|
  values += ", " if index > 0
  values += %((#{offer_id}, #{index}))
end
hot_offers = Offer.joins("join (VALUES #{values}) as x(id, ordering) on offers.id = x.id").order("x.ordering")

You can use this gem ( order_as_specified ) that allows you to do native SQL ordering like this:

Model.where(id: ids).order_as_specified(id: ids)

Reference Answer : Link

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM