我正在寻找解决以下问题的提示:
给定一个Neo4jDB,其中应用了两种节点类型作为标签
:地址和:里程碑(每个节点一个)
在不同的节点之间有指向:LEADS_TO关系。
给定以下模式(我跳过了关系的[]):
模式一:
(a:Address)->(:Milestone)->(:Milestone)<-(:Milestone)<-(:Milestone)<-(b:Address)
模式2:
(a:Address)->(:Milestone)->(c:Address)<-(:Milestone)<-(b: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
我最初的想法是创建第一跳:
对于Start节点
MATCH (a:Address)-[:LEADS_TO]->(aa:Milestone)
类似于结束节点并从那里开始查询。
但是这是有问题的,因为每个地址节点都可以有多个:LEADS_TO关系。查询定义的开始和结束节点的最短路径这种方法将为一个可以使用不同的开始和结束节点执行的查询创建n个开始节点和m个结束节点。
有人知道如何从Cypher中的WHERE子句中排除开始和结束节点吗?
任何提示都非常感谢。
试试这个,可以将集合的子集与切片运算符一起使用
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
您可以根据关系类型和节点不是开始或结束使用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]) )
绝对比我最初比赛的方法快。