路径之间特定节点标签的 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你们所有的里程碑节点。
我正在寻找解决以下问题的提示:
给定一个具有两种节点类型的 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你们所有的里程碑节点。