如何在Neo4j的家谱中减轻双向关系的影响?

3
我在双向关系方面遇到了困境。
比如说我试图创建一个代表家谱的图表。这里的问题是:
* Timmy可以是Suzie的哥哥,但
* Suzie不能是Timmy的哥哥。
因此,有必要在两个方向上对其进行建模:

enter image description here

(当然,从技术上讲,我可以使用SIBLING_TO并只留下一条边...但是当我尝试连接祖母和孙子时,我不确定词汇是什么。)

说到底,在这个例子中方向很重要,我相当确定这一点是无法避免的。

我正在阅读这篇博客文章,关于常见的Neo4j错误。作者指出,这种双向性不是在Neo4j中建模数据的最有效方式,应该避免使用。

我开始同意这种观点。我设置了一个模拟的2个家庭:
enter image description here 我发现我尝试运行的许多查询非常慢。这是由于图表的“所有连接到所有”的性质,至少在各自的家庭内是如此。

我的问题是:
1)我正确地说双向性不理想吗?

2) 如果可以,我的家谱示例是否可以用其他方式表示...在出现我的问题的许多情况下,什么是最佳实践?

3) 如果无法以其他方式表示家谱,则是否有技术上的可能以某种方式编写查询,以避免问题1)的影响?

感谢阅读和思考。


同名边的双向链接是多余的,没有增加价值。brother-to和sister-to传达了一些信息,但这可以从属性中推断出来。(child)-[:PARENT]->(parent)关系可以获得父母/子女关系,并且可以用于每一代的父母/孩子关系。继子女则是另一回事。 - Tim Kuehn
2个回答

1
在数据库中存储冗余信息(双向关系)从来不是一个好主意。以下是更好的表示家谱的方法。
为了表示“兄弟姐妹关系”,您只需要一个单一的关系类型,比如说SIBLING_OF,并且您只需要在两个兄弟姐妹节点之间有一个这样的关系。
为了表示祖先关系,您只需要一个单一的关系类型,比如说CHILD_OF,并且您只需要在每个孩子与其父母之间有一个这样的关系。
您还应该为每个人设置一个节点标签,比如说Person。每个人都应该有一个唯一的ID属性(比如说id),以及某种性别指示属性(比如说布尔型isMale)。
使用这个非常简单的数据模型,以下是一些示例查询:
  1. To find Person 123's sisters (note that the pattern does not specify a relationship direction):

    MATCH (p:Person {id: 123})-[:SIBLING_OF]-(sister:Person {isMale: false})
    RETURN sister;
    
  2. To find Person 123's grandfathers (note that this pattern specifies that matching paths must have a depth of 2):

    MATCH (p:Person {id: 123})-[:CHILD_OF*2..2]->(gf:Person {isMale: true})
    RETURN gf;
    
  3. To find Person 123's great-grandchildren:

    MATCH (p:Person {id: 123})<-[:CHILD_OF*3..3]-(ggc:Person)
    RETURN ggc;
    
  4. To find Person 123's maternal uncles:

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

这个答案正是我需要听到的 - 非常感谢。虽然方向性背后的想法在我的脑海中仍然模糊不清(为什么要应用方向性,如果它可能是无关的?),但减少冗余以使你拥有最少的关系的想法绝对是金子般的。示例查询非常棒。再次感谢。 - Monica Heddneck

0

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

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

由于我没有匹配方向,因此它将匹配两种方式。这是我建议建模的方式。

通常情况下,只有在您实际上想要存储不同状态时才需要建立多个关系。例如,KNOWS关系只能单向应用,因为A可能认识B,但B可能不认识A。同样,您可能会有一个带有值属性的LIKES关系,显示A喜欢B的程度,并且在两个方向上可能存在不同程度的“喜欢”。


你认为“孙女”和“祖母”是不同的状态,因此需要多个关系吗? - Monica Heddneck
我不这么认为... 我会说这两个关系是在数据库中表示同一状态的不同方式。这是Neo4j建模的一个方面。你需要选择一个并坚持使用它。 - Brian Underwood
更好的做法是,如果有意义的话,可以通过匹配两个child_of关系的路径来找到祖父母。但并不总是这样,你仍然想表示孙子关系。 - Brian Underwood
你的第二条评论让我大开眼界,我完全没有想到。我有一种直觉,应该用单向关系建模家谱,并尝试使用Cypher查询语言来获取我想要的结果。 - Monica Heddneck

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接