-
Type: Task
-
Resolution: Done
-
Affects Version/s: None
-
Component/s: None
-
Labels:None
Tried enabling identity map and everything went wrong.
It should be possible to support eager loading without an identity map. A poor man's implementation of that would look like this (tested, called it "project" instead of "eager_load", just for clarity):
ruby module Mongoid class Criteria def project(* relationship) if projected_entries.any? symbol = Array(relationship).last # eg. :artist klass = symbol.to_s.camelize.constantize # eg. Artist accessors = Array(relationship)[0..-2] # eg. [ :artwork ] parent = self.klass accessors.each do |accessor| parent = parent.relations[accessor.to_s].klass end # examine the relationship relation = parent.relations[symbol.to_s] # fetch the IDs target_ids = projected_entries.map do |entry| # apply any deep accessors to find the relationship parent accessors.each do |accessor| entry = entry.send(accessor) end entry[relation.foreign_key] if entry # id stored in the model end.compact.uniq # fetch the instances target_instances = Hash[klass.find(target_ids).map do |target_instance| [ target_instance.id, target_instance ] end] if target_ids.any? # project instances projected_entries.each do |entry| # apply any deep accessors accessors.each do |accessor| entry = entry.send(accessor) end # identity of the target instance target_instance = target_instances[entry[relation.foreign_key]] if entry entry.send("#{symbol}=", target_instance) if entry && target_instance end if target_instances end self end def projected_entries @projected_entries ||= entries end end end
You could then "project" any criteria and chain projections. Say you have a widget with many gadgets, and we're returning gadgets with their widgets.
ruby Gadget.limit(5).all.project(:widget).projected_entries
This would only do two queries: all gadgets and an $in for all widgets that belong to the first five gadgets.
Another way would be to introduce identity map only per query, without turning it on globally, but haven't tried that.
What do you think?