simonalexander2005
simonalexander2005

Reputation: 4577

Cypher find path avoiding certain node types except at the start and end

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 Stations, 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

Answers (2)

TheTeacher
TheTeacher

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

cybersam
cybersam

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

Related Questions