Reputation: 4577
I have a graph with the following structure:
(r:Region)-[:CONTAINS]-(s:Station)-[:IS_AT]-(t:TrackLocation)-[:IS_NEXT_TO]-(t:TrackLocation)
I want to find the shortest path between two Station
s, using only track locations. My current query is:
match (s1:Station) where s1.crs = 'ADR' match (s2:Station) where s2.crs = 'NRW' match p=shortestPath((s1)-[*1..1000]-(s2)) WHERE ALL (n IN nodes(p) WHERE NOT n:Region) return nodes(p)
.
The problem is, a station can be at multiple TrackLocations; and sometimes the shortest path can go via an intermediate Station node if it thinks this is quicker than sticking to TrackLocations for the intermediate nodes. If I change the filter to WHERE NOT n:Region AND NOT n:Station
, then of course it won't work because the start and end nodes are stations.
Is there any way to adjust this query to do (Station)-> via track locations only ->(Station)
?
Upvotes: 0
Views: 245
Reputation: 510
You can use OR logic here
match (s1:Station{crs: 'ADR'}), (s2:Station{crs : 'NRW'})
match p=shortestPath((s1)-[*1..1000]-(s2))
WHERE ALL (n IN nodes(p) WHERE n:TrackLocation or n = s1 or n = s2 ) return nodes(p)
Upvotes: 1
Reputation: 67044
If x
is a list, then the list operation x[1..-1]
returns a list with the second through next-to-last elements of x
.
This query uses that list operation to avoid testing the first and last nodes in the path:
MATCH (s1:Station), (s2:Station)
WHERE s1.crs = 'ADR' AND s2.crs = 'NRW'
MATCH p = shortestPath((s1)-[*..1000]-(s2))
WITH NODES(p) AS ns
WHERE ALL(n IN ns[1..-1] WHERE n:TrackLocation)
RETURN ns
Upvotes: 1