Neo4j GDS用Dijkstra求最短路径时如何限制最大途经街道数
问题解决方案
首先修正原有代码的语法问题:图投影语句的节点标签数组漏了逗号,['Person', 'Street' 'Restaurant'] 需要改成 ['Person', 'Street', 'Restaurant'],否则会直接抛出语法错误。
核心实现思路
绝对不要使用「先计算所有无约束最短路径,再在返回阶段过滤途经Street数量」的方案:由于Street节点两两互连,无约束遍历会生成海量超深路径,数据量级稍大就会直接触发内存溢出,必须在算法计算阶段就做深度剪枝。
你的数据模型下路径结构是完全固定的:
- 路径从Person节点出发,到Restaurant节点终止
- 路径中除起点Person、终点Restaurant外,所有中间节点均为Street标签
因此途经Street的数量和路径总跳数(关系数)存在固定换算关系:
最大允许途经Street数 = maxDepth参数值 - 1
示例:最多途经3个Street时maxDepth设为4;最多途经2个Street时maxDepth设为3
GDS的Dijkstra算法原生支持maxDepth配置参数,会在遍历过程中直接剪枝超过指定跳数的路径,性能损耗极低,完全适配大数据量、Street全互连的业务场景。
修改后可直接运行的代码
// 图投影(已修正原有语法错误) CALL gds.graph.project( 'Person-Street-Restaurant', ['Person', 'Street', 'Restaurant'], 'CONNECTION', { relationshipProperties: 'cost' } ) // 最多途经3个Street节点的最短路径计算 MATCH (source:Person{id:1}) CALL gds.allShortestPaths.dijkstra.stream('Person-Street-Restaurant', { sourceNode: source, relationshipWeightProperty: 'cost', maxDepth: 4 // 调整Street数量限制时修改该值即可,规则:maxDepth = 最大允许途经Street数 + 1 }) YIELD sourceNode, targetNode, totalCost, nodeIds WHERE 'Restaurant' IN LABELS(gds.util.asNode(targetNode)) RETURN gds.util.asNode(sourceNode).name AS sourceNodeName, gds.util.asNode(targetNode).name AS targetNodeName, totalCost, [nodeId IN nodeIds | gds.util.asNode(nodeId).name] AS nodeNames, SIZE([n IN nodeIds WHERE 'Street' IN LABELS(gds.util.asNode(n))]) AS passedStreetCount // 可选:返回实际途经Street数做校验 ORDER BY totalCost
效果验证
对照你给出的示例场景:
- 无约束时不设置maxDepth,会返回路径
P->S#3->S#4->S#5->R,总cost=7,途经3个Street,总跳数为4 - 限制最多途经2个Street时设置maxDepth=3,上述路径总跳数为4会被算法直接剪枝,最终返回符合要求的最优路径
P->S#1->S#2->R,总cost=10,和预期结果完全一致。
扩展说明
如果后续数据模型调整,路径中可能出现Street之外的中间节点,上述固定换算关系会失效。这种场景下可以使用GDS的自定义路径遍历接口,在节点访问阶段实时计数Street标签节点,超过阈值直接终止当前分支遍历,同样可以实现计算阶段剪枝,不会损失性能。
内容的提问来源于stack exchange,提问作者Goge Pow
相关产品推荐
相关产品推荐

