Reputation: 2233
I'm reviewing some code and I came across a line that does the following:
Person.find_by(name: "Tom").id
The above code gets the FIRST record with a name of "Tom", then builds a model, then gets the id of that model. Since we only want the id, the process of retreiving all data in the model and initializing the model is unneeded. What's the best way to optimize this using active record queries?
I'd like to avoid a raw sql solution. So far I have been able to come up with:
Person.where(name: "Tom").pluck(:id).first
This is faster in some situations since pluck
doesn't build the actual model object and doesn't load all the data. However, pluck
is going to build an array of records with name "Tom", whereas the original statement only ever returns a single object or nil - so this technique could potentially be worse depending on the where
statement. I'd like to avoid the array creation and potential for having a very long list of ids returned from the server. I could add a limit(1)
in the chain,
Person.where(name: "Tom").limit(1).pluck(:id).first
but is seems like I'm making this more complicated than it should be.
Upvotes: 4
Views: 3050
Reputation: 3
This might work depending on what you're looking for.
Person.where(name: "Tom").minimum(:id)
Person.where(name: "Tom").maximum(:id)
These will sort by id
value while the Person.where(name: "Tom").first.id
will sort off of your default sort. Which could be id, created_at, or primary_key.
eitherway test and see if it works for you
Upvotes: 0
Reputation: 6321
With Rails 6 you can use the new pick
method:
Person.where(name: 'Tom').pick(:id)
Upvotes: 4
Reputation: 4272
This is a little verbose, but you can use select_value from the ActiveRecord connection like this:
Person.connection.select_value(Person.select(:id).where(name: 'Tom').limit(1))
Upvotes: 1