从Graph获取文本格式的Path

时间:2014-10-23 07:17:36

标签: neo4j cypher

在我的图表中,我有以下方式的数据。

这里a,b,c,d是节点,r1,r2,r3,r4是关系。

a-r1->b
b-r2->a
b-r2->c
c-r1->b
d-r3->a
a-r1->d like this.

我正在使用Cypher来获取最大深度为3的路径。

MATCH p=(n)-[r*1..3]-(m) WHERE n.id=1 and m.id=2  RETURN p 

这里返回p是路径,我想以这样的文本格式显示路径。

示例:假设路径长度为3。 a-r1-> b-r2-> c这样的文本格式。

这可能吗?

2 个答案:

答案 0 :(得分:2)

排序。我会给你大部分答案,但我自己无法完成答案。也许另一个密码向导会出现并改进答案,但这就是我为你所做的。

match p=(n)-[r*1..3]-(m) 
WHERE id(n)=1 AND id(m)=2
WITH extract(node in nodes(p) | coalesce(node.label, "")) as nodeLabels,
     extract(rel in relationships(p) | type(rel)) as relationshipLabels
WITH reduce(nodePath="", nodeLabel in nodeLabels | nodePath + nodeLabel + "-") as nodePath,
     reduce(relPath="", relLabel in relationshipLabels | relPath + relLabel + "-") as relPath
RETURN nodePath, relPath
LIMIT 1;

编辑 - 一个小注释,在您的问题中,您指定了WHERE条件n.id=1 and m.id=2。请注意,这可能不是您想要的。通常使用WHERE id(n)=1 AND id(m)=2检查节点ID。我在技术上并不是一个节点属性,所以我改变了它。

好的,所以我们要匹配路径。然后我们将使用extract函数从节点中提取label属性,并创建一个名为nodeLabels的集合。我们对关系类型也这样做。这里reduce的作用是将这些集合中的每个字符串累积到一个字符串。因此,如果您的节点是a,b和c,那么您将获得一个类似于nodePath的{​​{1}}字符串。同样,您的关系字符串看起来像a-b-c-

现在,我知道您希望这些交错,并且您更喜欢r1-r2-r3-之类的输出。这是我看到的问题...

通常,我接近的方法是使用FOREACH迭代节点标签集合。既然你知道由于路径的原因,节点之间的关系比节点少,理想情况下(在伪代码中)我想做这样的事情:

a-r1-b-r2-c

这将是一种减少你想要的字符串的方法。您无法使用buffer = "" foreach x in range(0, length(nodeLabels)) | buffer = buffer + nodeLabels[idx] + "-" + relLabels[idx] + "->") 功能,因为它无法为您提供获取您在集合中所处的索引的方法。这意味着您可以迭代其中一个集合,但不能同时迭代另一个集合。这个reduce伪代码不起作用,因为我认为FOREACH的第二部分必须是图形上的变异操作,你不能只用它来积累像我这样的字符串在这里做过,或者像FOREACH函数那样。

据我所知,你可能会被困在这里。希望有人会证明我错了 - 我不是百分百肯定。

最后另一种方法是,如果有一个路径函数提取节点/关系对,而不是单独extractnodes(),就像我上面使用它们一样,那么你可以使用该函数迭代一个集合,而不是洗牌两个集合,因为我上面的代码尝试并且没有做到。可悲的是,我不认为有任何这样的路径功能,所以这就是为什么我认为你可能会成为一条小溪的原因。

现在,实际上,您总是可以用java或其他语言执行此查询,返回路径,然后使用您想要构建此字符串的任何编程语言的全部功能。但纯粹的密码?我很怀疑。

答案 1 :(得分:1)

这是我最终做的事情。希望其他人发现它对未来有用。

MATCH p=(n)-[r*1..3]->(m) 
WHERE n.id=1 AND m.id=4
WITH extract(rel in relationships(p) | STARTNODE(rel).name + '->' + type(rel)) as relationshipLabels,  m.name as endnodename
WITH reduce(relPath="", relLabel in relationshipLabels | relPath + relLabel+ '->') as relPath , end
RETURN distinct relPath +  endnodename