Mongoid has_many关系在枚举时返回伪数据

时间:2015-02-12 23:34:23

标签: ruby-on-rails mongodb mongoid

我将给出一个快速背景。我正在使用以下(汇总)模型在Rails中构建有向图:

Node
has_many :edges, foreign_key: "source_id"

Edge
field :source_id, :type => String
field :destination_id, :type => String
belongs_to :source, class_name: "Node"
belongs_to :destination, class_name: "Node"

我遇到过Mongoid has_many和belongs_to关系的两个奇怪问题。关系查询的结果似乎取决于我用来检索Node对象的方法。

首先,在关系上调用to_a(以及枚举关系,即eachmapcollect)会导致要检索的额外Edge,如下所示,计数返回为31。

第二次,只有当检索Edge的查询与直接Node不同时,才会出现额外find的问题。但正如您所看到的,根据Rails node1等于node2

如果有人能对这些问题有所了解,我将不胜感激。如果有其他信息可以帮助我,请告诉我。

1.9.3-p327 :145 > node1 = some_other_node.neighbors.select {|n| n[:node].city == "983"}.first[:node]
 => #<Node _id: 54da32b1756275343ed70300, city: "983"> 

1.9.3-p327 :140 > node2 = Node.find_by(:city => "983")
 => #<Node _id: 54da32b1756275343ed70300, city: "983"> 

1.9.3-p327 :141 > node1 == node2
 => true 

1.9.3-p327 :150 > node1.edges.count
 => 30 
1.9.3-p327 :151 > node1.edges.to_a.count
 => 31 
1.9.3-p327 :152 > node2.edges.count
 => 30 
1.9.3-p327 :153 > node2.edges.to_a.count
 => 30

编辑提供有关额外优势的信息。

返回的额外Edge应返回绝对不。您可以在下面看到额外的Edge sourcenode1 不等于。返回的每个其他Edge都有node1作为来源,这正是我根据关系所期望的。

1.9.3-p327 :167 >   node1.edges.to_a.last.source
 => #<Node _id: 54da32b0756275343e000000, city: "0"> 

以下是支持我的主张的更多证据。请注意,所有node2边都有node2作为source,但node1不适用。

1.9.3-p327 :170 > node2.edges.to_a.collect {|e| e.source == node2}.include? false
 => false 
1.9.3-p327 :171 > node1.edges.to_a.collect {|e| e.source == node1}.include? false
 => true

但是,额外的Edgecity: "0"作为来源是很奇怪的,因为在node1的初始分配中some_other_nodecity: "0"。这似乎不是巧合。

1 个答案:

答案 0 :(得分:1)

问题解决了!谢谢你的建议mu太短了。当我试图在out_edges上实现in_edgesNode时,我发现Mongoid抱怨反向关系模棱两可。有趣的是,当我只定义out_edges时,它很高兴。

只是为了澄清,定义out_edgesin_edges需要,我能够通过包含inverse_of来消除缺陷Edge模型中的定义。

Node
    has_many :edges, foreign_key: "source_id"

Edge
    field :source_id, :type => String
    field :destination_id, :type => String
    belongs_to :source, inverse_of: "edges", class_name: "Node"
    belongs_to :destination, inverse_of: "in_edges", class_name: "Node"

修改

Rails / Mongoid似乎并不关心destination是否使用inverse_of: "in_edges"定义,即使Node中不存在in_edges。但是,如果我删除该部分,则问题将返回。 Mongoid肯定有一些缺陷。