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
(以及枚举关系,即 each
、map
、collect
) 导致额外的 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
然而,额外的 Edge
将 city: "0"
作为来源是很奇怪的,因为在 node1
的初始分配中 some_other_node
是 city: "0"
.这似乎不是巧合。
问题已解决!感谢您的建议 mu 太短了。当我尝试在 Node
上实现 out_edges
和 in_edges
时,我发现 Mongoid 抱怨逆关系不明确。有趣的是,当我只定义 out_edges
.
时,它很高兴地保持沉默
澄清一下,不需要 来定义 out_edges
和 in_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 肯定有一些缺陷。
我会快速介绍一下背景。我正在 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
(以及枚举关系,即 each
、map
、collect
) 导致额外的 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
然而,额外的 Edge
将 city: "0"
作为来源是很奇怪的,因为在 node1
的初始分配中 some_other_node
是 city: "0"
.这似乎不是巧合。
问题已解决!感谢您的建议 mu 太短了。当我尝试在 Node
上实现 out_edges
和 in_edges
时,我发现 Mongoid 抱怨逆关系不明确。有趣的是,当我只定义 out_edges
.
澄清一下,不需要 来定义 out_edges
和 in_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 肯定有一些缺陷。