neo4j和单向关系

时间:2015-07-09 12:55:41

标签: neo4j

我是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)。那么,我做错了什么以及使用什么是正确的查询?

2 个答案:

答案 0 :(得分:3)

neo4j中的所有关系都是定向的。当您说(n)-[:foo]->(m)时,该关系只有一种方式,从nm

现在关于这一点很棘手的是你可以双向导航这种关系。这不会使关系成双向,它永远不会 - 它只意味着你可以在任何一个方向上看它。

当您编写此查询时:(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中的

ID

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中单向和双向关系的更多信息

现在我们已经处理了示例中的一些基本问题,让我们来解决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_OFCHILD_OF关系?

答案是否定的。我们可以选择其中一种关系,无论哪种模型都是最佳模型,并且仍然可以搜索两种方式。

仅使用:PARENT_OF关系,我们可以

MATCH (mary {name:'Mary'})-[:PARENT_OF]->(children) RETURN children

找到孩子,或

MATCH (mary {name:'Mary'})<-[:PARENT_OF]-(parents) RETURN parents

寻找父母,每次都以(玛丽)为起点。

有关详细信息,请see this fantastic article from GraphAware