cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

How to retrieve relationship properties from shortest path algorithm?

Hi, there.
I am new with neo4j. I am trying to get a shortest path between two nodes.
I am using the Shortest Path algorithm in the Neo4j Graph Data Science library.
It is easy to get the shortest path. However, I also want more information from the relationships.

Here my cyphers:
// Nodes
MERGE (a:Loc {name:'A'})
MERGE (b:Loc {name:'B'})
MERGE (c:Loc {name:'C'})
// Relationship
MERGE (a)-[:ROAD {cost:2, type:'Path'}]->(b)
MERGE (b)-[:ROAD {cost:1, type:'Lift'}]->(c)
MERGE (a)-[:ROAD {cost:5, type:'Path'}]->(c);
// Get Shortest Path
MATCH (start:Loc{name:"A"}), (end:Loc{name:"C"})
CALL gds.alpha.shortestPath.stream({
nodeQuery:'MATCH(n:Loc) RETURN id(n) AS id',
relationshipQuery:'MATCH(n:Loc)-[r:ROAD]->(m:Loc) RETURN id(n) AS source, id(m) AS target, r.cost AS cost',
startNode: start,
endNode: end,
relationshipWeightProperty: 'cost'
})
YIELD nodeId, cost
RETURN gds.util.asNode(nodeId).name AS name, cost;

// Cypher Result:
| name | cost |
| "A" | 0.0 |
| "B" | 2.0 |
| "C" | 3.0 |

But, I want to have the result like below:
| Source | Target | Road.Type | Road.cost |
| "A" | "B" | "Path" | 2.0 |
| "B" | "C" | "Lift" | 1.0 |

How can I achieve that?
Thank you for helping me.

13 REPLIES 13

Hello @Terry.Y,
I think that this could be a possible solution:

MATCH (start:Loc{name:"A"}), (end:Loc{name:"C"})
CALL gds.alpha.shortestPath.stream({
nodeQuery:'MATCH(n:Loc) RETURN id(n) AS id',
relationshipQuery:'MATCH(n:Loc)-[r:ROAD]->(m:Loc) RETURN id(n) AS source, id(m) AS target, r.cost AS cost',
startNode: start,
endNode: end,
relationshipWeightProperty: 'cost'
})
YIELD nodeId, cost
RETURN gds.util.asNode(nodeId).name AS name, end.name as Target, r.Type as Road.Type, cost;

Could you made a try? I'm not sure that I've understood well, but I hope to be able to help you.

Tobia

Thank you Tobia.

Variable r not defined (line 10, column 66 (offset: 393))
"RETURN gds.util.asNode(nodeId).name AS name, end.name as Target, r.Type as Type, cost"

It seems r (the relationship) cannot be referenced.

Oh, ok.
Maybe you've to add it in the first MATCH, because I noticed now that you've add it only inside the CALL and so your query cannot use it. If you want to use it, you've to add it in MATCH.

MATCH (start:Loc{name:"A"}), (end:Loc{name:"C"}), (start)-[r:ROAD]->(end)
CALL gds.alpha.shortestPath.stream({
nodeQuery:'MATCH(n:Loc) RETURN id(n) AS id',
relationshipQuery:'MATCH(n:Loc)-[r:ROAD]->(m:Loc) RETURN id(n) AS source, id(m) AS target, r.cost AS cost',
startNode: start,
endNode: end,
relationshipWeightProperty: 'cost'
})
YIELD nodeId, cost
RETURN gds.util.asNode(nodeId).name AS name, end.name as Target, r.Type as Road.Type, cost;

In this way, you should be able to print, but I'm sure that this will be fully correct, maybe we need to do another step.

To get relationship label the syntax is type(r):

RETURN gds.util.asNode(nodeId).name AS name, end.name as Target, type(r) as Type, cost;

I want to retrieve the relationship data in the shortest path. Anyone can help?
(a)-[:ROAD {cost:2, type:'Path'}]->(b)
(b)-[:ROAD {cost:1, type:'Lift'}]->(c)

| Source | Target | Type | cost |
| "A" | "B" | "Path" | 2.0 |
| "B" | "C" | "Lift" | 1.0 |

Many thanks.

match(a:Loc)-[r:ROAD]->(b:Loc)
where a.name = "A" and b.name = "B"
return a.name as Source, b.name as Target, r.type as Type, r.cost as Cost

union

match(b:Loc)-[r:ROAD]->(c:Loc)
where c.name = "C" and b.name = "B"
return b.name as Source, c.name as Target, r.type as Type, r.cost as Cost

This would be a possible way. That means we have to run extra queries.
Thanks.

Try this. This shows three paths, A-B, A-C and B-C:
 
MATCH(n:Loc)-[r:ROAD]->(m:Loc) RETURN n.name AS source, m.name AS target, r.cost AS cost, r.type as RoadType

Add r.type as RoadType in the RETURN statement to get the road type in the final result.

MATCH (start:Loc{name:"A"}), (end:Loc{name:"C"}), (start)-[r:ROAD]->(end)
CALL gds.alpha.shortestPath.stream({
nodeQuery:'MATCH(n:Loc) RETURN id(n) AS id',
relationshipQuery:'MATCH(n:Loc)-[r:ROAD]->(m:Loc) RETURN id(n) AS source, id(m) AS target, r.cost AS cost, r.type as RoadType',
startNode: start,
endNode: end,
relationshipWeightProperty: 'cost'
})
YIELD nodeId, cost
RETURN gds.util.asNode(nodeId).name AS name, end.name as Target, RoadType, cost;

Thank you so much, ameyasoft.
In fact, it doesn't work.
RoadType in relationshipQuery cannot be returned. If it can be returned, my problem would be solved.
I just want to have the information in relationshipQuery, such as source, target, and type.
However, it cannot be returned in the result.

I'm encoutering the exact same problem, I managed to get the relationship types between each step, but instead of returning the relationship that guided the shortest path algorithm, I get every single relationship between each node.

MATCH (start:Loc{name:"A"}), (end:Loc{name:"C"}), (start)-[r:ROAD]->(end)
CALL gds.alpha.shortestPath.stream({
nodeQuery:'MATCH(n:Loc) RETURN id(n) AS id',
relationshipQuery:'MATCH(n:Loc)-[r:ROAD]->(m:Loc) RETURN id(n) AS source, id(m) AS target, r.cost AS cost',
startNode: start,
endNode: end,
relationshipWeightProperty: 'cost'
})
YIELD nodeId, cost
RETURN gds.util.asNode(nodeId).name AS name, end.name as Target, type(r) as roadType, cost;

Did you manage to solve this issue?

I raised an issue about this in the GDS Github repo. The discussion there might be of some use for those who find this discussion.