3

Let's say I have an articles table with thousands of articles. I am trying to figure out the most performant way to find the 5 longest article names, not the articles themselves.

This is what I have so far:

def self.five_longest_article_names
  limit(5).order("(LENGTH(name)) desc").pluck(:name)
end

But that uses SQL. Is there an ActiveRecord query that I could have performed instead?

Jwan622
  • 11,015
  • 21
  • 88
  • 181

2 Answers2

4
YourModel.limit(5).order("CHAR_LENGTH(name) desc").pluck(:name)

So, your method becomes:

def self.five_longest_article_names
  limit(5).order("CHAR_LENGTH(name) desc").pluck(:name)
end

You could defintely use Arel, but Arels are good for complex queries. In your case, this is a simple usecase, and I think it's better to use SQL in this particular case.

K M Rakibul Islam
  • 33,760
  • 12
  • 89
  • 110
  • thanks! In simplest world... what's the difference between Arel and AR? – Jwan622 Sep 03 '15 at 21:59
  • In short, `Arel` is a SQL AST manager for Ruby. It `Simplifies the generation of complex SQL queries`. And, `Active Record` is the M in MVC - the model - which is the layer of the system responsible for representing business data and logic. `Active Record facilitates the creation and use of business objects` whose data requires persistent storage to a database. – K M Rakibul Islam Sep 03 '15 at 22:04
  • `Arel` is a replacement for hand-crafting SQL queries in strings. See the accepted answer from this thread: http://stackoverflow.com/questions/2770415/what-exactly-is-arel-in-rails-3-0 to know more about Arel, what is it and what it is not :) – K M Rakibul Islam Sep 03 '15 at 22:08
0

You can always create your own name function for arel:

my_length = Arel::Nodes::NamedFunction.new('LENGTH', YourModel.table[:name])

YourModel.order(Arel::Nodes::Descending.new(my_length)).limit(5)
# or
YourModel.order("#{my_length.to_sql} DESC").limit(5)

I'd suggest you pass it as a named scope to your model and concatenate calls from there.

ChuckE
  • 5,610
  • 4
  • 31
  • 59