Reputation: 3230
When I query the embedded model, no records are returned despite there being plenty of parent records containing instances of the embedded model.
There are two models, a Label
embedded in a Band
:
class Band
include Mongoid::Document
embeds_one :label
end
class Label
include Mongoid::Document
field :name, type: String
embedded_in :band
end
I can query Band (Band.all
, Band.find
etc) just fine, but when I query Label, it returns nothing. For instance:
I create the band with the embedded label, and save it:
> b = Band.create
=> #<Band _id: 516cff525543d8842e000008, _type: nil>
> b.build_label name: "new label"
=> #<Label _id: 516cff5a5543d8842e000009, _type: nil, name: "new label">
> b.save
=> true
Then I query the Band model, and all is fine:
> Band.all.to_a
=> [#<Band _id: 516cff525543d8842e000008, _type: nil>]
> Band.count
=> 1
> Band.first.label
=> #<Label _id: 516cff5a5543d8842e000009, _type: nil, name: "new label">
> Band.find "516cff525543d8842e000008"
=> #<Band _id: 516cff525543d8842e000008, _type: nil>
But when I query the Label model, nothing shows up!
> Label.all.to_a
=> []
> Label.count
=> 0
> Label.last
=> nil
> Label.first
=> nil
> Label.find "516cff5a5543d8842e000009" # this is the label id from Band
=> nil
I'm almost positive this is not intended behavior. The code is directly from an example on the Mongoid docs here: http://mongoid.org/en/mongoid/docs/relations.html#embeds_one
What am I missing?
Upvotes: 1
Views: 1063
Reputation: 714
In mongo your queries always target collections, i.e. full documents that may embed other documents. For mongo it's just one big JSON/BSON document. Now, Label.all
or Label.all
are equivalent to querying the Label
collection. Since labels are not stored in the Label
collection, those queries return nothing. However, you can still query labels on the Band
collection by calling
Band.where(:'labels._id' => "516cff5a5543d8842e000009")
or something like
Band.where(:'labels.name' => "rock")
This is fine if you want to get all bands with a certain label. Getting all labels this way, however, is very expensive and not recommended. What's your main use case? If it is showing labels for a band or getting bands with a certain label, then embedding is great. Otherwise, you could use relations (has_many/belongs_to), or denormalize completely, i.e. save labels within bands and in a separate collection at the same time (leading to redundant data).
Upvotes: 2
Reputation: 794
I think you should use has_many, has_one, belongs_to methods for making possible to run queries as you want like Label.count.
When you embed document into another document it will become as a part(serialized property) of a document. If you want to select labels you should find Band at first and then check the label property. It should definitely work.
Upvotes: 0