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

Mongoid has_many relation returning fake data when enumerated

我会快速介绍一下背景。我正在 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"

我遇到了 2 个关于 Mongoid has_many 和 belongs_to 关系的奇怪问题。关系查询的结果似乎因我用来检索 Node 对象的方法而异。

First,在关系上调用 to_a(以及枚举关系,即 eachmapcollect) 导致额外的 Edge 被检索,如下所示,其中计数 returns 为 31.

Second,额外 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 有一个 source,它 不等于 node1。返回的每个其他 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".这似乎不是巧合。

问题已解决!感谢您的建议 mu 太短了。当我尝试在 Node 上实现 out_edgesin_edges 时,我发现 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" 定义的,即使 in_edges 在 Node.js 中不存在。但是,如果我删除那部分,那么问题 returns。 Mongoid 肯定有一些缺陷。