So I have two Class that look's like this
class Branch
include MongoMapper::Document
many :builds
end
class Build
include MongoMapper::Document
belongs_to :branch
end
And If we want to access Branch
data from Build
Class. I can do it like below
builds = Build.where(___)
builds.each do |build|
puts "#{build.branch.name} build number #{build.number}"
end
But that triggers an alert that causing N+1 queries because it makes too many independent database queries. Well the solution is by using Eager Load like below
builds = Build.where(____).includes(:branches)
builds.each do |build|
puts "#{build.branch.name} build number #{build.number}"
end
Well, eager loading or .includes()
are not available in MongoMapper as I looking from their's documentation (I Hope I wrong). But it is available in MongoId. But, I'm not planning to change from MongoMapper into MongoId for now. Do you know the turn around for this? that maybe can reduce the queries.
According to the docs Mongoid's #includes
"...Will load all the documents into the identity map who's ids match based on the extra query for the ids."
So there is no magic at all - it sounds like it just performs an additional query to fetch the associated entities and keep them in memory in some kind of data structure with O(1) reads (Hash in Ruby, for example). You can do it on your own (disclaimer: kinda pseudocode is coming, as a reference, not a ready solution):
builds = #...
branches = Branch.where(id: builds.map(&:id)).to_h { |br| [br.id, br] }
builds.each do |build|
puts "#{branches[build.branch_id]&.name} build number #{build.number}"
end
But please note: if you have to do this kind of memorization often it might be a signal that the data model is not optimal for the document-based database - embedded documents might be a more efficient solution...