如何使用elementId替代id调用Neo4j的gds.shortestPath.dijkstra.stream?
问题描述
我有一个由节点和关系(n1:Place)-[r:COST]->(n2:Place)投影得到的图。为了找到名称为'a'和'z'的两个节点间的最便宜路径,我使用Dijkstra最短路径算法:
MATCH (start:Place) where 'a' = start.name MATCH (end:Place) where 'z' = end.name CALL gds.shortestPath.dijkstra.stream('my-graph',{ sourceNode: id(start), targetNode: id(end), relationshipWeightProperty: 'cost' }) YIELD nodeIds
这段代码运行正常,但我了解到id(node):int已被弃用,在Neo4j 1.5.8中应使用新的elementId(node):string函数替代。于是修改代码为:
MATCH (start:Place) where 'a' = start.name MATCH (end:Place) where 'z' = end.name CALL gds.shortestPath.dijkstra.stream('my-graph',{ sourceNode: elementId(start), targetNode: elementId(end), relationshipWeightProperty: 'cost' }) YIELD nodeIds
但由于elementId()返回字符串而非整数,运行时抛出异常:
Failed to invoke procedure `gds.shortestPath.dijkstra.stream`: Caused by: java.lang.IllegalArgumentException: Expected a node or a node id for `sourceNode`. Got String.
请问是否有其他支持使用elementId()替代id()进行路径查找的方案?
解决方案
方法1:直接传入节点对象
GDS的最短路径过程支持直接传入节点对象,无需转换为ID,这是最简洁的处理方式,同时避开ID类型兼容问题:
MATCH (start:Place) where start.name = 'a' MATCH (end:Place) where end.name = 'z' CALL gds.shortestPath.dijkstra.stream('my-graph',{ sourceNode: start, targetNode: end, relationshipWeightProperty: 'cost' }) YIELD nodeIds RETURN nodeIds
方法2:投影图时保留elementId属性
若必须基于elementId进行匹配,可以在图投影阶段将节点的elementId作为属性存入投影图,后续通过属性匹配获取对应节点的内部ID:
- 重新投影图并添加elementId属性:
CALL gds.graph.project( 'my-graph-with-elementId', 'Place', 'COST', { nodeProperties: { elementId: elementId(node) } } )
- 查询时通过
gds.util.nodeProperty()定位节点:
MATCH (start:Place) where start.name = 'a' MATCH (end:Place) where end.name = 'z' WITH elementId(start) as startElementId, elementId(end) as endElementId CALL gds.shortestPath.dijkstra.stream('my-graph-with-elementId',{ sourceNode: gds.util.nodeProperty('my-graph-with-elementId', startElementId, 'elementId'), targetNode: gds.util.nodeProperty('my-graph-with-elementId', endElementId, 'elementId'), relationshipWeightProperty: 'cost' }) YIELD nodeIds RETURN nodeIds
方法3:使用gds.findNode()函数(GDS 2.5+)
如果你的Neo4j GDS版本在2.5及以上,可以使用gds.findNode()函数,通过elementId直接获取投影图中的节点引用:
MATCH (start:Place) where start.name = 'a' MATCH (end:Place) where end.name = 'z' CALL gds.shortestPath.dijkstra.stream('my-graph',{ sourceNode: gds.findNode('my-graph', elementId(start)), targetNode: gds.findNode('my-graph', elementId(end)), relationshipWeightProperty: 'cost' }) YIELD nodeIds RETURN nodeIds
内容的提问来源于stack exchange,提问作者Andrés Meza-Escallón
相关产品推荐
相关产品推荐

