导入graph databases的语言,了解
图形(由维基百科提供)描述了directed graph。
也就是说,所有边都是倒数的图形(,如上图),并且无论方向如何,每条边的属性都相同(与上图相反)。
假设通过ActiveRecord使用sql存储设置默认的Rails 3设置。
双polymorphic association会创建有向图,能够对上图所描述的数据进行建模。
def Edge < ActiveRecord::Base
belongs_to :head, polymorphic: true
belongs_to :tail, polymorphic: true
end
class Node < ActiveRecord::Base
has_many :from, as: :head
has_many :to, as: :tail
end
class Group < ActiveRecord::Base
# a Node of Type: Group
has_many :from, as: :head
has_many :to, as: :tail
end
是否应该扩展此模型以管理反向关系,或者是更好的模型?
应用程序的一个元素可能是图形问题,但并不意味着应用程序以问题为中心,必须对数据执行图表横向,数据集也不大于可用内存。
答案 0 :(得分:12)
在无向图中,您唯一需要知道的是节点是否连接到另一个节点。而且没有方向这样的东西。
简单方法:
class Node
has_many :connected_nodes
has_many :nodes, :through => :connected_nodes
end
class ConnectedNode
belongs_to :node
belongs_to :connected_node, :class_name => 'Node'
end
这也称为邻接列表:对于每个节点,我们可以轻松获得相邻(连接)节点的列表。
此方法可能存在的问题是:我们将连接存储两次。 A连接到B,B连接到A.
因此,将每个连接只存储一次似乎更合理,然后我们就会非常接近原始提案。
class Connection
belongs_to :node1, :class_name => 'Node'
belongs_to :node2, :clasS_name => 'Node'
end
只有我们尽最大努力不通过命名强加任何命令或方向。
检索连接的节点是连接到node1
或node2
的所有节点,因此有效地忽略了任何可能的方向。
在这种情况下,您还需要表明与(node1,node2)的连接是唯一的验证,但是(node2,node1)实际上是相同的,并且不能插入两次。
我个人的选择是使用第二个模式,尽管保持第一个解决方案可能会更快(另请参阅此question)。
我还发现了一个非常有趣的article,其中作者解释了图表如何存储在数据库中。非常深刻,但更加以数据库为中心。
希望这有帮助。
答案 1 :(得分:3)
尝试使用has_many,:through
,而不是使用多态关联class Group < ActiveRecord::Base
has_many :memberships
has_many :persons, :through => :memberships
end
class Membership < ActiveRecord::Base
belongs_to :group
belongs_to :person
end
class Person < ActiveRecord::Base
has_many :memberships
has_many :groups, :through => :memberships
end
您可以在成员资格模型中存储边缘的属性。
答案 2 :(得分:2)