Spring Boot本地/Docker环境调用Neo4j计算最短路径异常排查
Spring Boot Neo4j最短路径功能异常修复方案
1. 测试类认证失败异常修复
运行测试抛出org.neo4j.driver.exceptions.AuthenticationException是连接配置不匹配导致的,按以下步骤排查修复:
- 本地运行测试/启动项目时,不要直接使用docker-compose中为容器配置的内部连接参数。
bolt://neo4j-db:7687是Docker内部网络域名,物理机无法直接访问,需要在项目测试配置文件src/test/resources/application.yml(或properties)中添加本地连接配置:
spring: neo4j: uri: bolt://localhost:7687 authentication: username: neo4j password: 123456
- 如果你之前启动过其他Neo4j容器,本地挂载目录
$HOME/neo4j/data中残留了旧的认证凭证,会覆盖docker-compose中设置的NEO4J_AUTH初始密码。直接清空$HOME/neo4j目录下所有内容,重新执行docker-compose up -d启动容器,Neo4j会重新初始化你配置的账号密码。 - 跑测试前先验证Neo4j服务状态:执行
docker ps确认app-neo4j-db容器状态为healthy,再访问本地7474端口的Neo4j控制台,用neo4j/123456能正常登录,再执行测试就不会抛出认证异常。
2. 大数据量下带权最短路径实现方案
Neo4j自带的shortestPath()函数仅支持计算最少跳数的无权重路径,要基于路径时长属性计算最短路径,适配十万级以上城市、路线数据场景,按以下方式实现:
- 第一步:补全GDS插件配置
你的docker-compose中已经放开了GDS插件的权限,但默认Neo4j 4.3镜像不带GDS插件,需要把对应版本的GDS插件jar包放到本地挂载的$HOME/neo4j/plugins目录下,重启Neo4j容器让插件生效。 - 第二步:初始化内存图投影(大数据量场景必做)
为了避免每次查询都遍历磁盘存储,先执行一次Cypher语句将城市节点、路线关系投影到GDS内存图中,查询性能会提升2~3个数量级:
CALL gds.graph.project( 'cityRouteGraph', 'City', { ROUTE: { properties: 'duration', orientation: 'UNDIRECTED' -- 如果路线是单向通行就删掉这行 } } );
- 第三步:编写Dijkstra最短路径查询
在Repository层编写基于GDS Dijkstra算法的查询语句,自动按duration属性计算权重最小的路径:
@Query("MATCH (start:City {name: $startCity}), (end:City {name: $endCity}) " + "CALL gds.shortestPath.dijkstra.stream('cityRouteGraph', { " + " sourceNode: id(start), " + " targetNode: id(end), " + " relationshipWeightProperty: 'duration' " + "}) YIELD nodeIds, costs " + "RETURN [node in gds.util.asNodes(nodeIds) | node.name] AS pathNodes, " + "costs[-1] AS totalDuration") List<PathResult> calculateShortestPath(String startCity, String endCity);
- 功能验证:可以先插入测试数据校验结果正确性
CREATE (bj:City {name:'北京'}), (tj:City {name:'天津'}), (sjz:City {name:'石家庄'}), (jn:City {name:'济南'}) CREATE (bj)-[:ROUTE {duration:1.5}]->(tj), (tj)-[:ROUTE {duration:4}]->(jn), (bj)-[:ROUTE {duration:3}]->(sjz), (sjz)-[:ROUTE {duration:3}]->(jn)
调用接口查询北京到济南的最短路径,预期返回路径为北京->天津->济南,总时长5.5,即表示功能正常。如果后续路线、节点数据有更新,重新执行一次图投影语句即可同步内存数据。
内容的提问来源于stack exchange,提问作者Sercan Noyan Germiyanoğlu
相关产品推荐
相关产品推荐

