I have two model with has_many belongs to relation.
Scheme has_many navs
I need to fetch all the Schemes with only last nav value. I have 10 Schemes and each scheme has around 100k navs but I need only last record which is the current value.
With eager loading will load all the navs
Scheme.all.includes(:navs)
How can I apply condition to to get only last row of nav for each schemes while eager loading.
UPDATE with Log
If I run
Scheme.includes(:current_nav).limit(3)
these are the queries executed by AR
SELECT `schemes`.* FROM `schemes` LIMIT 3
SELECT `navs`.* FROM `navs` WHERE `navs`.`schemeCode` IN ('D04', 'D01', 'D30') ORDER BY id DESC
How the second query works, it will take all the navs whose schemeCode falls under list and order those by id DESC , but how it will be associated with particular scheme exactly.
How about creating an another association like this:
class Scheme < ActiveRecord::Base
has_one :current_nav, -> { order('id DESC').limit(1) }, class_name: 'Nav'
end
Now you can:
Schema.includes(:current_nav).all
or:
Schema.includes(:current_nav).last(10)
will eager load only last nav of the queried schemes.
Explanation: includes
is one of the methods for retrieving objects from database in ActiveRecord
. From the doc itself:
Active Record lets you specify in advance all the associations that are going to be loaded. This is possible by specifying the includes method of the Model.find call. With includes, Active Record ensures that all of the specified associations are loaded using the minimum possible number of queries.
And, since we have the association setup with current_nav
, all we had to do is to use it with includes
to eager load the data. Please read ActiveRecord querying doc for more information.