我是neo4j
的新手。我刚刚阅读了有关此工具的一些信息,将其安装在Ubuntu上并进行了大量查询。在这一刻,我必须承认,我真的很喜欢它。但是,有些东西(我认为非常简单和直观),我不知道如何实现。所以,我创建了三个节点:
CREATE (n:Object {id:1}) RETURN n
CREATE (n:Object {id:2}) RETURN n
CREATE (n:Object {id:3}) RETURN n
我在他们之间建立了一种等级关系:
MATCH (a:Object {id:1}), (b:Object {id:2}) CREATE (a)-[:PARENT]->(b)
MATCH (a:Object {id:2}), (b:Object {id:3}) CREATE (a)-[:PARENT]->(b)
所以,我认为这个简单的层次结构应该是这样的:
(id:1)
-> (id:2)
-> (id:3)
我现在想要的是从任何节点获取路径。例如,如果我想从节点(id:2)获得路径,我将得到(id:2) - > (ID:3)。如果我想从节点(id:1)获取路径,我将得到(id:1) - >(id:2) - >(id:3)。我试过这个问题:
MATCH (n:Object {id:2})-[*]-(children) return n, children
我应该返回一个路径(id:2) - >(id:3),但意外地(仅为我)它返回(id:1) - >(id:2) - >( ID:3)。那么,我做错了什么以及使用什么是正确的查询?
答案 0 :(得分:3)
neo4j中的所有关系都是定向的。当您说(n)-[:foo]->(m)
时,该关系只有一种方式,从n
到m
。
现在关于这一点很棘手的是你可以双向导航这种关系。这不会使关系成双向,它永远不会 - 它只意味着你可以在任何一个方向上看它。
当您编写此查询时:(n:Object {id:2})-[*]-(children)
您没有在该关系上放置箭头,因此children
可以引用相关节点的下游或上游的某些内容。
换句话说,说(n)-[:test]-(m)
与匹配(n)<-[:test]-(m)
和 (n)-[:test]->(m)
是一回事。
因此children
可以引用ID 1对象或ID 2对象。
答案 1 :(得分:1)
直接回答你的问题,
您的查询
MATCH (n:Object {id:2})-[*]-(children) return n, children
不仅匹配关系 FROM (n {id:2})
TO 其子女,还关系 TO (n {id:2})
来自其父母。
您还需要另外指定您喜欢的方向。这将返回您期望的结果:
MATCH (n:Object {id:2})-[*]->(children) return n, children
我想回答您关于单向和双向关系的评论,但让我们先解决一些问题。
让我们重新审视你的例子:
(:Object {id:1})-[:PARENT]->(:Object {id:2})-[:PARENT]->(:Object {id:3})
使用:Object
,:Node
,:Thing
等标签毫无意义。如果你真的不在乎,根本就不要使用标签!
在这种情况下,它看起来我们在谈论人,虽然它也很容易成为主板和子板,或其他东西!
让我们使用People而不是Objects:
(:Person {id:1})-[:PARENT]->(:Person {id:2})-[:PARENT]->(:Person {id:3})
Neo4j中的 Neo4j存储自己的每个节点和关系的ID。您可以使用id(nodeOrRelationship)
检索这些ID,并使用WHERE
子句通过ID进行访问,或者将其指定为匹配的起点。 START n=node(2) MATCH (n)-[*]-(children) return n, children
相当于原始查询MATCH (n:Object {id:2})-[*]-(children) return n, children
。
让我们而不是ID存储有关节点的有用信息,例如名称:
(:Person {name:'Bob'})-[:PARENT]->(:Person {name:'Mary'})-[:PARENT]->(:Person {name:'Tom'})
最后,让我们消除歧义。 PARENT
表示&#34;是&#34;的父级,或者#34;是否有此父级&#34;?你可能很清楚你的意思是哪一个,但是对你的系统不熟悉的人可能会有相反的解释。
我认为你的意思是&#34;是&#34;的父母,所以让我们说清楚:
(:Person {name:'Bob'})-[:PARENT_OF]->(:Person {name:'Mary'})-[:PARENT_OF]->(:Person {name:'Tom'})
现在我们已经处理了示例中的一些基本问题,让我们来解决Neo4j和图表中关系的方向性。
我们可以用几种方式表达这个例子的关系。我们来看几个。
为了讨论的目的,让我们抽象一下上面使用的父关系:
(bob)-[:KIN]-(mary)-[:KIN]-(tom)
此处关系KIN
表示它们相关,但我们并不确切知道谁是其父母。汤姆是玛丽的孩子,反之亦然吗?
请注意,我没有使用任何箭头。在上面的图形伪代码中,KIN
关系是双向或无向关系。
然而,Neo4j中的关系总是方向性的。如果KIN
关系确实是您想要跟踪的内容,那么您就可以创建方向关系,但始终忽略MATCH
个查询中的方向,例如MATCH (a)-[:KIN]-(b)
而非MATCH (a)-[:KIN]->(b)
。
但是KIN
关系真的是存储这些信息的最佳方式吗?我们可以使它更具体。让我们回到我们之前使用的PARENT_OF
关系。
回到例子。我们知道Bob是Tom的父母Mary的父母:
(bob)-[:PARENT_OF]->(mary)-[:PARENT_OF]->(tom)
显然,这样做的必然结果是:
(bob)<-[:CHILD_OF]-(mary)<-[:CHILD_OF]-(tom)
或等同地:
(tom)-[:CHILD_OF]->(mary)-[:CHILD_OF]->(bob)
那么,我们是否应该继续创建我们的(bob),(mary)和(tom)节点之间的PARENT_OF
和CHILD_OF
关系?
答案是否定的。我们可以选择其中一种关系,无论哪种模型都是最佳模型,并且仍然可以搜索两种方式。
仅使用:PARENT_OF
关系,我们可以
MATCH (mary {name:'Mary'})-[:PARENT_OF]->(children) RETURN children
找到孩子,或
MATCH (mary {name:'Mary'})<-[:PARENT_OF]-(parents) RETURN parents
寻找父母,每次都以(玛丽)为起点。