Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
06-20-2020 03:01 AM
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.
06-20-2020 05:12 AM
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
06-20-2020 05:46 AM
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.
06-20-2020 06:00 AM
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.
06-20-2020 06:11 AM
06-20-2020 12:50 PM
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;
06-21-2020 01:53 AM
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.
06-21-2020 09:39 AM
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
06-21-2020 07:48 PM
This would be a possible way. That means we have to run extra queries.
Thanks.
06-22-2020 11:08 AM
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
06-21-2020 09:43 AM
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;
06-21-2020 07:44 PM
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.
12-26-2020 10:43 AM
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?
03-19-2021 07:33 AM
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.
All the sessions of the conference are now available online