2

I have the following models:

class Foo
 has_and_belongs_to_many :bars
end

class Bar
 has_and_belongs_to_many :foos
end

Each document representing the Foo instance has an array field called bar_ids. When ever a Foo object is retrieved from the DB, Mongoid retrieves the contents of the bar_ids also. When the document has 1000s of ids this can cause performance issues, i.e.

> Foo.first
#<Foo _id: 4fed60aa2bdf061c2c000001, bar_ids: [1, 2, 3.... 5000]>

In most cases I don't need to load the bar_ids. Is there way I can instruct the model to lazy load the bar_ids?

Harish Shetty
  • 64,083
  • 21
  • 152
  • 198

1 Answers1

2

I asked the same question in the mongoid group and got an answer. Essentially, one need to read the documentation of three gems to understand mongoid 3 ( mongoid, moped, and origin).

Here is the relevant documentation section of origin gem. The without or only clause can be used to filter the resulting document structure.

Loading selectively:

Foo.without(:bar_ids).first

Reloading selectively:

def reload_fields(*fields)
  return self if fields.empty? or new_record?
  # unscope and prevent loading from indentity map
  fresh = Mongoid.unit_of_work(disable: :current) do
    self.class.unscoped.only(*fields).find(id)
  end
  fields.each do |attr| 
    write_attribute(attr, fresh.read_attribute(attr))
    remove_change(attr) # unset the dirty flag for the reloaded field
  end
  self
end
Harish Shetty
  • 64,083
  • 21
  • 152
  • 198