如何在Apache AGE中正确执行基于travelTime的最短路径查询
Apache AGE中实现Neo4j交通路由的最短路径查询
我正在将一篇博客中的Neo4j交通路由逻辑移植到Apache AGE中:构建一个包含Metro标签顶点和HAS_ROUTE标签边的图,边带有travelTime属性表示通行时间。原Neo4j的最短路径查询在Apache AGE中执行时出现语法错误,需要调整写法以正确获取两点间的最短路径。
原Neo4j查询:
MATCH paths = (a:Metro {name: 'Cavite Island'})-[:HAS_ROUTE*1..6]-(b:Metro {name: 'NYC'}) WITH paths, relationships(paths) AS rels UNWIND rels AS rel WITH [metro IN nodes(paths) | metro.name] AS metros, collect(rel.travelTime) AS streets, sum(rel.travelTime) AS travelTime ORDER BY travelTime RETURN metros, streets, travelTime
在Apache AGE中执行时报错Syntax error at or near "|",尝试带reduce的写法也报同样错误。
语法差异说明
Apache AGE的Cypher实现与标准Neo4j Cypher存在部分语法差异:
- 不支持
[item IN list | item.property]这种列表推导式语法 reduce函数无需重复末尾的初始值参数
正确查询写法
方式1:枚举所有路径并按总时间排序
与原Neo4j查询逻辑一致,通过拆解列表推导式实现:
SELECT * from cypher('Saxeburg', $$ MATCH paths = (a:Metro {name: 'Cavite Island'})-[:HAS_ROUTE*1..6]-(b:Metro {name: 'NYC'}) WITH paths, relationships(paths) AS rels UNWIND rels AS rel WITH paths, collect(rel.travelTime) AS streets, sum(rel.travelTime) AS travelTime UNWIND nodes(paths) AS metro WITH paths, streets, travelTime, collect(metro.name) AS metros ORDER BY travelTime RETURN metros, streets, travelTime $$) as (metros agtype, streets agtype, travelTime agtype);
方式2:使用最短路径函数(更高效)
如果仅需最短时间路径,推荐使用Apache AGE的图算法函数,效率更高:
SELECT * from cypher('Saxeburg', $$ MATCH (start:Metro {name: 'Cavite Island'}), (end:Metro {name: 'NYC'}) CALL gds.shortestPath.dijkstra.stream({ nodeProjection: 'Metro', relationshipProjection: { HAS_ROUTE: { type: 'HAS_ROUTE', properties: 'travelTime', orientation: 'UNDIRECTED' } }, startNode: start, endNode: end, relationshipWeightProperty: 'travelTime' }) YIELD nodeIds, totalCost WITH [nodeId IN nodeIds | gds.util.asNode(nodeId).name] AS metros, totalCost AS travelTime RETURN metros, travelTime $$) as (metros agtype, travelTime agtype);
修正reduce函数的写法
若需手动计算路径总时间,AGE中reduce的正确语法如下:
SELECT * FROM cypher('demo', $$ MATCH path = (from:Metro {name:'Brooklyn'})-[:HAS_ROUTE*]-(to:Metro {name:'Phoenix'}) RETURN path AS shortestPath, reduce(travelTime = 0, r IN relationships(path) | travelTime + r.travelTime) AS totalTravelTime ORDER BY totalTravelTime LIMIT 1 $$) as (shortestPath agtype, totalTravelTime agtype);
内容的提问来源于stack exchange,提问作者Matheus Farias
相关产品推荐
相关产品推荐

