路径之间特定节点标签的 Neo4j 最短路径

Neo4j Shortest Path for specific node labels in-between the path

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

给定一个具有两种节点类型的 Neo4j 数据库作为标签

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

不同节点之间存在定向的:LEADS_TO 关系。

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

模式 1:

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

模式二:

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

我正在寻找在最短路径分析中仅包含 "in-between" 相同类型节点的查询。在我的例子中,它应该只包含标签为 :Milestone 的节点,并跳过标签为 :Address 的较短路径。

换句话说:查询应该匹配模式 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 子句中排除开始和结束节点?

非常感谢任何提示。

您可以使用基于关系类型和节点不是开始或结束的 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]) )

感谢您的帮助。它稍作修改即可工作。我不得不再添加两个括号(围绕 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]) )

绝对比我的初始匹配方法快。

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

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

像这样使用 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))

它将return你们所有的里程碑节点。