Jeremy Smith
Jeremy Smith

Reputation: 15069

How can one mongoid model query another?

If I have a model called Product

class Product
  include Mongoid::Document

  field :product_id
  field :brand
  field :name
  ...

  belongs_to :store

And then I have a model called Store

class Store
  include Mongoid::Document

  field :name
  field :store_id
  ...

  has_many :products

  def featured_products
    Products.where(:feature.exists => true).and(store_id: self[:store_id]).asc(:feature).asc(:name)
  end

How do I create an accessible @store.featured_products which is the results of this query? Right now I get an error that reads

uninitialized constant Store::Products

Upvotes: 0

Views: 209

Answers (2)

ABrowne
ABrowne

Reputation: 1604

I just stumbled on this looking for something else and although the above answer is correct, and the question is ages old, it is very inefficient for what is being asked. As I stumbled on it, so might others.

The example usage above wished to scope the products relationship to just featured products, so a model such as this would work faster (assumed Mongoid 3.0+):

class Product
  include Mongoid::Document

  field :product_id
  field :brand
  field :name
  field :feature
  ...

  belongs_to :store

  scope :featured, where(:feature.exists => true).asc(:feature).asc(:name)

end

class Store
  include Mongoid::Document

  field :name
  field :store_id
  ...

  has_many :products
end

Then instead of @store.featured_products, you could call @store.products.featured. Now if you assume Mongoid 2.x was used, as this was 2011, and looking at this then Mongoid 1.x maybe not have had scopes, the same thing could be achieved like this:

class Product
  include Mongoid::Document

  field :product_id
  field :brand
  field :name
  field :feature
  ...

  belongs_to :store
end

class Store
  include Mongoid::Document

  field :name
  field :store_id
  ...

  has_many :products

  def featured_products
     self.products.where(:feature.exists => true).asc(:feature).asc(:name)
  end
end

Now the reason both of these are more efficient that just a boolean search on the Products collection is that they start with a cursor creation across the _id field. This is indexed and limits the subsequent where query to just the related documents. The difference would be noticeable on most collection sizes, however the bigger the collection grew the more time would be wasted on a boolean of the entire collection.

Upvotes: 0

rdvdijk
rdvdijk

Reputation: 4398

Use Product, not Products.

Upvotes: 1

Related Questions