我正在寻找解决以下问题的提示:
给定一个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子句中排除开始和结束节点?
非常感谢任何提示。
答案 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))
它将返回所有里程碑节点。