遍历Cypher

时间:2017-11-22 16:12:26

标签: neo4j cypher

我是Neo4j的新手,但不是图表,我有一个特定的问题,我无法用Cypher解决。

使用此类数据:

Data model

我希望能够在单个查询中跟踪一些传入流和一些传出流。

示例:

  • 从" source"
  • 开始
  • 关注所有" A"外向的关系
  • 关注所有" B"传入方式的关系

我的问题是Cypher只允许在关系模式中指定一个方向。

所以我可以做(source)-[:A|:B*]->() or (source)<-[:A|:B*]-()。 但我无法告诉Cypher我想要关注-[:A]-> and <-[:B]-

顺便说一句,我知道我可以做-[:A|:B]-,但这不会解决我的问题,因为我不想关注-[:B]-><-[:A]-

提前感谢您的帮助:)

2 个答案:

答案 0 :(得分:2)

除了@Gabor Szarnyas的回答,我认为您可以使用APOC程序apoc.path.expand来实现目标。

使用此样本数据集:

CREATE (:Source)-[:A]->()-[:A]->()<-[:B]-()-[:A]->()

并致电apoc.path.expand

match (source:Source)
call apoc.path.expand(source,"A>|<B","",0,5) yield path
return path

您将获得此路径作为输出:

Output

apoc.path.expand来自source-[:A]->关系之后<-[:B]-节点的呼叫。

请记住根据您使用的Neo4j版本安装APOC procedures。请查看version compatibility matrix

答案 1 :(得分:1)

要在单个查询中表达这一点,需要一个常规路径查询,已经提出并accepted to openCypher,但它尚未实现。

我看到两种可能的解决方法。我使用此命令重新创建了您的示例,并为源节点添加了Source标签:

CREATE (:Source)-[:A]->()-[:A]->()<-[:B]-()-[:A]->()

(1)插入具有相同方向的其他关系:

MATCH (s)-[:B]->(t)
CREATE (s)<-[:B2]-(t)

并使用此关系进行遍历:

MATCH p=(source)-[:A|:B2*]->()
RETURN p

(2)如你所说:

  

顺便说一句,我知道我能做到 - [:A |:B] - 但这不能解决我的问题,因为我不想跟随 - [:B] - &gt;和&lt; - [:A] - 。

您可以使用此方法首先获取潜在的路径候选者,然后手动检查关系的方向。当然,这是一项昂贵的操作,但您只需要在候选项上进行计算,这可能是一个很小的数据集。

MATCH p=(source:Source)-[:A|:B*]-()
WITH p, nodes(p) AS nodes, relationships(p) AS rels
WHERE all(i IN range(0, size(rels) - 1) WHERE
  CASE type(rels[i]) 
    WHEN 'A' THEN startNode(rels[i]) = nodes[i]
    ELSE /* B */  startNode(rels[i]) = nodes[i+1]
  END)
RETURN p

让我们分解一下这是如何运作的:

  • 我们将路径候选项存储在p中,并使用nodesrelationships函数从中提取节点/关系列表。
  • 我们为关系定义range个索引(例如,如果有3个关系,则来自0, 1, 2。)
  • 要确定关系的方向,我们使用startNode函数。例如,如果节点rn1之间存在关系n2,则路径将为<n1, r, n2>。如果在传出方向上移动了rstartNode(r)将返回n1,如果它在传入方向上移动,则startNode(r)将返回n2。使用type函数检查关系的类型,并使用simple CASE表达式来区分类型。
  • WHERE子句使用all谓词函数检查所有:A:B关系是否具有相应的路线。