3

关于双向关系,我遇到了这堵墙。

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

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

在此处输入图像描述

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

当一切都说完了,我很确定在这个例子中方向很重要这一事实是没有办法的。

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

我开始同意了。我建立了一个由 2 个系列组成的模拟集:
在此处输入图像描述 我发现我尝试运行的很多查询都非常非常慢。这是因为图表的“所有连接到所有”的性质,至少在每个相应的系列中。

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

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

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

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

4

2 回答 2

1

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

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

要表明祖先,您只需要一个关系类型,例如CHILD_OF,并且您只需要在孩子与其每个父母之间建立一个这样的关系。

您还应该为每个人设置一个节点标签,例如Person. 并且每个人都应该有一个唯一的 ID 属性(例如id)和某种指示性别的属性(例如 boolean 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 的曾孙:

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

    MATCH (p:Person {id: 123})-[:CHILD_OF]->(:Person {isMale: false})-[:SIBLING_OF]-(maternalUncle:Person {isMale: true})
    RETURN maternalUncle;
    
于 2016-04-27T22:21:56.953 回答
0

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

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

并且由于我不匹配方向,因此它将双向匹配。这就是我建议的建模方式。

通常,如果您实际上想要存储不同的状态,您只想建立多个关系。例如,KNOWS关系只能以一种方式应用,因为 A 可能认识 B,但 B 可能不认识 A。类似地,您可能LIKES与显示 A 喜欢 B 的值属性建立关系,并且“喜欢”两个方向

于 2016-04-27T04:31:40.833 回答