2013-04-16 108 views
1

当我查询嵌入式模型时,尽管存在大量包含嵌入式模型实例的父记录,但没有记录被返回。Mongoid嵌入式文档返回空查询

有两种模式,嵌入Band一个Label

class Band 
    include Mongoid::Document 
    embeds_one :label 
end 

class Label 
    include Mongoid::Document 
    field :name, type: String 
    embedded_in :band 
end 

我可以查询乐队(Band.allBand.find等)就好了,但是当我查询标签,它没有返回。例如:

创建与嵌入式标签带,并将其保存:

> 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 

然后我查询了带模型,所有的罚款:

> 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> 

但是,当我查询标签模型,什么也没有显示!

> Label.all.to_a 
=> [] 
> Label.count 
=> 0 
> Label.last 
=> nil 
> Label.first 
=> nil 
> Label.find "516cff5a5543d8842e000009" # this is the label id from Band 
=> nil 

我几乎肯定这不是预期的行为。代码直接来自Mongoid文档的示例:http://mongoid.org/en/mongoid/docs/relations.html#embeds_one

我错过了什么?

回答

2

在mongo中,您的查询始终以集合为目标,即可能嵌入其他文档的完整文档。对于mongo,它只是一个大的JSON/BSON文档。现在,Label.allLabel.all相当于查询Label集合。由于标签未存储在Label集合中,所以这些查询不会返回任何内容。但是,您仍然可以通过调用

Band.where(:'labels._id' => "516cff5a5543d8842e000009") 

或类似

Band.where(:'labels.name' => "rock") 

,如果你想获得的所有乐队同一个标签下这是好的查询在Band收集标签。然而,通过这种方式获得所有标签非常昂贵并且不推荐。你的主要用例是什么?如果它显示乐队的标签或获得具有特定标签的乐队,那么嵌入效果非常好。否则,您可以使用关系(has_many/belongs_to)或完全非规范化,即将标签保存在波段中并同时保存在单独的集合中(导致冗余数据)。

+0

感谢您的明确解释。我没有特定的用例,我只是注意到它,并认为这是一种奇怪的行为 - 当你对嵌入式Mongoid模型进行查询时,Mongoid是否不应该至少发出警告? –

+0

@SherwinYu,你是对的,因为它是不直观的,即使它是可以理解的。不幸的是,这是Mongoid的许多(不常见)角落的情况,所以要小心:) –

0

我认为你应该使用has_many,has_one,belongs_to方法来使得像Label.count一样运行查询。

当您将文档嵌入到另一个文档中时,它将成为文档的一部分(序列化属性)。如果你想选择标签,你应该先找到Band,然后检查标签属性。它应该肯定有效。

+0

确定吗?这似乎不是默认行为,即使是嵌入式文档也很不直观。 –