Neo4j路径

时间:2016-06-16 17:10:55

标签: neo4j cypher shortest-path

我正在寻找解决以下问题的提示:

给定一个Neo4j数据库,其中两个节点类型应用为标签

:地址和:里程碑(每个节点一个)

在不同节点之间有指向:LEADS_TO关系。

给出以下模式(我跳过关系的[]):

模式1:

(a:Address)->(:Milestone)->(:Milestone)<-(:Milestone)<-(:Milestone)<-(b:Address)

模式2:

(a:Address)->(:Milestone)->(c:Address)<-(:Milestone)<-(b:Address)

我正在寻找一个只包含shortestPath分析中相同类型的“中间”节点的查询。在我的情况下,它应该只包含带有标签的节点:Milestone并跳过具有标记节点的较短路径:地址介于两者之间。

换句话说:查询应该匹配模式1而不是模式2,即使它更短。

我发现以下解决方案接近但在我的情况下失败,因为它也涵盖了开始和结束节点标签,因此根本不选择任何行:

MATCH p=shortestPath( (a:Address)-[:LEADS_TO*..10]-(b:Address) ) 
WHERE a.name = 'XYZ'
AND b.name = 'ABC'
AND ALL(x IN nodes(p) WHERE (x:MILESTONE))
RETURN p

我最初的想法是创建第一跳:

对于“开始”节点

MATCH (a:Address)-[:LEADS_TO]->(aa:Milestone)

和端节点类似,并从那里开始查询。

但这是有问题的,因为每个:Address节点可以有多个:LEADS_TO关系。查询定义的起始和结束节点的最短路径,这种方法将为一个查询创建n个起始节点和m个终端节点,这些查询可以使用不同的起始节点和结束节点执行。

有没有人知道如何从Cypher中的WHERE子句中排除开始和结束节点?

非常感谢任何提示。

4 个答案:

答案 0 :(得分:6)

试试这个,您可以使用带有切片运算符的集合的子集

MATCH p=shortestPath( (a:Address)-[:LEADS_TO*..10]-(b:Address) ) 
WHERE a.name = 'XYZ'
AND b.name = 'ABC'
AND ALL(x IN nodes(p)[1..-1] WHERE (x:MILESTONE))
RETURN p

答案 1 :(得分:4)

您可以使用基于关系类型的WHERE ALL子句以及不是开始或结束的节点,例如:

MATCH p=shortestPath( (a:Address)-[:LEADS_TO*..10]-(b:Address) ) 
WHERE a.name = 'XYZ'
AND b.name = 'ABC'
AND ALL( x IN range( 1, size(nodes(p)-2) ) 
         WHERE 'Milestone' IN labels(nodes(p)[x]) )

答案 2 :(得分:0)

感谢您的帮助。它的工作稍作修改。我不得不再添加两个括号(围绕size方法),以确保返回节点中的大小计算正确。

MATCH p=shortestPath( (a:Address)-[:LEADS_TO*..10]-(b:Address) ) 
WHERE a.name = 'XYZ'
AND b.name = 'ABC'
AND ALL( x IN range( 1, (size(nodes(p))-2) ) 
     WHERE 'Milestone' IN labels(nodes(p)[x]) )

绝对比我的初始比赛方法快。

答案 3 :(得分:0)

如何使用filter():

MATCH p=shortestPath( (a:Address)-[:LEADS_TO*..10]-(b:Address) ) 
WHERE a.name = 'XYZ'
AND b.name = 'ABC'
RETURN FILTER(x IN nodes(p) WHERE 'Milestone' IN labels(x))

它将返回所有里程碑节点。