1

I have the array [5, 3, 1, 4] which corresponds to the hash keys produced by the following code:

@ordered_hash = Review.group('aidmodel_id').average('score')
@ordered_hash = ActiveSupport::OrderedHash[@ordered_hash.sort_by {|key, value| value }]
@keys = @ordered_hash.keys

Using the keys obtained @keys = [5, 3, 1, 4] I would like to pull some records from my database using:

@reviews = Review.where(:aidmodel_id=>@keys).uniq_by {|x| x.aidmodel_id}

This works well. However, the returned models are in the order that they appear in the database, rather than in the order specified by the keys. This means that the output is sorted randomly, rather than in order of average score.

There must be some way to re-order the multidimensional array returned by Review.where based on the @keys array.. or some way to pull the records out in the correct order.. perhaps using a loop around the SQL query?

Thanks for your help!!

2
  • "the returned models are in the order that they appear in the database" isn't quite right, there is no order in the database unless you explicitly ORDER BY. Commented Mar 18, 2012 at 18:25
  • Sorry I mean the order of their IDs Commented Mar 18, 2012 at 19:16

2 Answers 2

1

You can optimize your first two statements to use the DB sorting, as the rails group functions return OrderedHash

# you can order the result set by the select col position instead of name
avg_scores  = Review.average(:score, :group => :aidmodel_id, :order => "2 ASC")
# assuming you don't have 100s of rows here..
rh = Review.where(:aidmodel_id=> @avg_scores.keys).group_by(&:aidmodel_id)
avg_score_set = avg_scores.map {|id, score| [id, score, rh[id]]}

Now avg_score_set is a ordered array of arrays. The inner array has the avg score and reviews.

Sign up to request clarification or add additional context in comments.

4 Comments

.average returns an OrderedHash, not a relation object. Hooray for consistent interfaces!
@muistooshort, you are right, I updated my answer to address the issue.
Eventually the table will have 100s of rows.. Do you think implementing the above code will pose a risk? Thanks.
It depends upon how you want to access the review rows. If you are trying to list them then you are better off paginating the result set for a specific aidmodel_id.
1

I wouldn't know about Ruby, but in PostgreSQL you can get array elements in the requested order like this:

SELECT arr[i] AS arr_element
FROM  (SELECT '{1,2,3,4,5}'::int[] AS arr, unnest(ARRAY[5, 3, 1, 4]) AS i) x

2 Comments

Thanks Erwin. What is the relevance of the {1,2,3,4,5} in your code above?
@Abram: '{1,2,3,4,5}'::int[] is one of several ways to input an array literal. Another one would be: ARRAY[1,2,3,4,5]. More about that in the manual.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.