2016-04-27 100 views
2

我在双向关系中遇到了这堵墙。如何减轻Neo4j中家族树中的双向关系?

假设我试图创建一个代表家族树的图。这里的问题是:
*蒂米可以是苏丝的兄弟,但
*苏丝不能是蒂米的兄弟。

因此,有必要在两个方向来模拟这种:

enter image description here

(当然,技术上我可以说SIBLING_TO,只留下一个边缘......什么我不知道的词汇是当我试图将奶奶连接到孙子时。)

当这一切都说完之后,我非常确定在这个例子中方向很重要。

我正在读这个blog post,关于常见的Neo4j错误。作者指出,这种双向性不是在Neo4j中建模数据的最有效方式,应该避免。

我开始同意。我建立了2个系列的模拟集:
enter image description here 我发现我试图运行的很多查询都非常缓慢。这是因为图表的“全部连接到所有”性质,至少在每个相应的家庭中。

我的问题是这样的:
1)我正确地说双向性不理想吗? 2)如果是这样,我的家庭树的例子是以任何其他方式表示的......在我的问题可能发生的许多情况下,什么是'最佳实践'?

3)如果无法用另一种方式表示家谱,技术上仍然可以以某种方式写出查询以解决1)的问题?

感谢您阅读本文和您的想法。

+0

相同边缘名的双向链接是多余的,不能增加价值。兄弟和姊妹传达一些信息,尽管这可以从物业推断出来。一个(孩子) - [:家长] - >(父母)关系让你成为父母/孩子的关系,并让你获得整个生物家庭关系,并且可以为每一代父母/孩子使用它。一步一步的孩子将是另一回事。 –

回答

1

将冗余信息(双向关系)存储在数据库中绝不是一个好主意。这是表示家谱的更好方法。

为了表示“兄弟姐妹”,您只需要一种关系类型,比如SIBLING_OF,并且您只需要在两个兄弟节点之间有一个这样的关系。

为了表示祖先,你只需要一种关系类型,比如说CHILD_OF,你只需要在一个孩子与其父母之间有一个这样的关系。

您还应该为每个人设置节点标签,如Person。每个人都应该有一个唯一的ID属性(比如id),以及某种指示性别的属性(比如布尔值isMale)。

有了这个非常简单的数据模型,这里有一些样本查询:

  1. 要找到人123的姐妹们(注意,模式没有指定关系方向):

    MATCH (p:Person {id: 123})-[:SIBLING_OF]-(sister:Person {isMale: false}) 
    RETURN sister; 
    
  2. 要找到Person 123的祖父(请注意,此图案指定匹配路径必须具有2的深度):

    MATCH (p:Person {id: 123})-[:CHILD_OF*2..2]->(gf:Person {isMale: true}) 
    RETURN gf; 
    
  3. 要找到人123的曾孙:

    MATCH (p:Person {id: 123})<-[:CHILD_OF*3..3]-(ggc:Person) 
    RETURN ggc; 
    
  4. 要找到人123的舅舅:

    MATCH (p:Person {id: 123})-[:CHILD_OF]->(:Person {isMale: false})-[:SIBLING_OF]-(maternalUncle:Person {isMale: true}) 
    RETURN maternalUncle; 
    
+0

这个答案正是我需要听到的 - 非常感谢你。尽管方向性背后的想法在我的脑海中仍然是粗略的(为什么要应用方向,如果可能或不可能不相关?),减少冗余以使您拥有最少关系的想法绝对是黄金。示例查询太棒了。再次感谢。 –

0

我不确定是否知道可以双向查询(即忽略方向)。所以你可以这样做:

MATCH (a)-[:SIBLING_OF]-(b) 

因为我不匹配一个方向它会匹配两种方式。这是我建议如何建模的东西。

一般而言,如果您真的想存储不同的状态,您只需要创建多个关系。例如KNOWS关系只能应用一种方式,因为人A可能知道人B,但B可能不知道A.同样,您可能有一个LIKES与值属性的关系,该值属性显示A像B一样多,并且可能有不同的优势在两个方向上“喜欢”

+0

你是否同意''的'孙女'和'祖母'是不同的国家,因此需要多重关系? –

+0

我不这么认为......我会说这两种关系是表达数据库中相同状态的不同方式。这是Neo4j中建模的一个方面。你需要选择一个并坚持下去 –

+0

尽管如此,如果对你有意义,最好还是通过匹配两个孩子关系的路径找到祖父母。但你并不总是那样,你仍然想代表孙子关系 –