在 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
)。
使用这个非常简单的数据模型,这里有一些示例查询:
查找Person 123的姐妹(注意模式不指定关系方向):
MATCH (p:Person {id: 123})-[:SIBLING_OF]-(sister:Person {isMale: false})
RETURN sister;
查找 Person 123 的祖父(注意此模式指定匹配路径的深度必须为 2):
MATCH (p:Person {id: 123})-[:CHILD_OF*2..2]->(gf:Person {isMale: true})
RETURN gf;
要找到 Person 123 的 great-grandchildren:
MATCH (p:Person {id: 123})<-[:CHILD_OF*3..3]-(ggc:Person)
RETURN ggc;
寻找123号的舅舅:
MATCH (p:Person {id: 123})-[:CHILD_OF]->(:Person {isMale: false})-[:SIBLING_OF]-(maternalUncle:Person {isMale: true})
RETURN maternalUncle;
关于双向关系,我运行陷入困境。
假设我正在尝试创建一个代表家谱的图表。这里的问题是:
* Timmy 可以是 Suzie 的弟弟,但是
* Suzie 不能是 Timmy 的兄弟。
因此,有必要在两个方向上对其进行建模:
(当然,从技术上讲,我可以说 SIBLING_TO 并且只留下一个边...当我尝试将祖母与孙子联系起来时,我不确定词汇是什么。)
当一切都说完之后,我很确定在这个例子中方向很重要这一事实是无法回避的。
我正在读这个 blog post,关于常见的 Neo4j 错误。作者指出,这种双向性不是在 Neo4j 中建模数据的最有效方式,应该避免。
我开始同意了。我设置了一组模拟的 2 个家庭:
我的问题是:
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
)。
使用这个非常简单的数据模型,这里有一些示例查询:
查找Person 123的姐妹(注意模式不指定关系方向):
MATCH (p:Person {id: 123})-[:SIBLING_OF]-(sister:Person {isMale: false}) RETURN sister;
查找 Person 123 的祖父(注意此模式指定匹配路径的深度必须为 2):
MATCH (p:Person {id: 123})-[:CHILD_OF*2..2]->(gf:Person {isMale: true}) RETURN gf;
要找到 Person 123 的 great-grandchildren:
MATCH (p:Person {id: 123})<-[:CHILD_OF*3..3]-(ggc:Person) RETURN ggc;
寻找123号的舅舅:
MATCH (p:Person {id: 123})-[:CHILD_OF]->(:Person {isMale: false})-[:SIBLING_OF]-(maternalUncle:Person {isMale: true}) RETURN maternalUncle;