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

How can I mitigate having bidirectional relationships in a family tree, in Neo4j?

关于双向关系,我运行陷入困境。

假设我正在尝试创建一个代表家谱的图表。这里的问题是:
* Timmy 可以是 Suzie 的弟弟,但是
* Suzie 不能是 Timmy 的兄弟。

因此,有必要在两个方向上对其进行建模:

(当然,从技术上讲,我可以说 SIBLING_TO 并且只留下一个边...当我尝试将祖母与孙子联系起来时,我不确定词汇是什么。)

当一切都说完之后,我很确定在这个例子中方向很重要这一事实是无法回避的。

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

我开始同意了。我设置了一组模拟的 2 个家庭:
我发现我尝试 运行 的很多查询都非常非常慢。这是因为图表的 'all connected to all' 性质,至少在每个各自的家族中。

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

2) 如果是这样,我的家谱示例是否可以用任何其他方式表示...在我的问题可能出现的许多情况下,'best practice' 是什么?

3) 如果不可能以另一种方式表示家谱,在技术上是否仍然可以以某种方式编写查询来绕过 1) 的问题?

感谢您阅读本文并提出您的想法。

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

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

因为我没有匹配方向,所以它会匹配两种方式。这就是我建议建模的方式。

一般来说,如果你真的想存储不同的状态,你只想建立多个关系。例如,KNOWS 关系只能以一种方式应用,因为 A 可能认识 B,但 B 可能不认识 A。同样,您可能有一个 LIKES 关系,其值 属性 显示A有多喜欢B,两个方向"liking"的强度可能不同

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

要表示"siblingness",你只需要一个关系类型,比如SIBLING_OF,你只需要在2个兄弟节点之间有一个这样的关系。

要表示祖先,您只需要一种关系类型,比如说 CHILD_OF,并且您只需要在 child 和它的每个 parents 之间有一个这样的关系.

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

使用这个非常简单的数据模型,这里有一些示例查询:

  1. 查找Person 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. 要找到 Person 123 的 great-grandchildren:

    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;