简体   繁体   中英

How to get a path from one node to another including all other nodes and relationships involved in between

I have designed a model in Neo4j in order to get paths from one station to another including platforms/legs involved. The model is depicted down here. Basically, I need a query to take me from NBW to RD. also shows the platforms and legs involved. I am struggling with the query. I get no result. Appreciate if someone helps.

Here is my cypher statement:

MATCH p = (a:Station)-[r:Goto|can_board|can_alight|has_platfrom*0..]->(c:Station)
WHERE (a.name='NBW') 
AND c.name='RD' 
RETURN p

Model: 在此处输入图片说明

As mentioned in the comments, in Cypher you can't use a directed variable-length relationship that uses differing directions for some of the relationships.

However, APOC Procedures just added the ability to expand based on sequences of relationships. You can give this a try:

MATCH (start:station), (end:station)
WHERE start.name='NBW' AND end.name='THT'
CALL apoc.path.expandConfig(start, {terminatorNodes:[end], limit:1,
  relationshipFilter:'has_platform>, can_board>, goto>, can_alight>, <has_platform'}) YIELD path
RETURN path 

I added a limit so that only the first (and shortest) path to your end station will be returned. Removing the limit isn't advisable, since this will continue to repeat the relationships in the expansion, going from station to station, until it finds all possible ways to get to your end station, which could hang your query.

EDIT

Regarding the new model changes, the reason the above will not work is because relationship sequences can't contain a variable-length sequence within them. You have 2 goto> relationships to traverse, but only one is specified in the sequence.

Here's an alternative that doesn't use sequences, just a whitelisting of allowed relationships. The spanningTree() procedure uses NODE_GLOBAL uniqueness so there will only be a single unique path to each node found (paths will not backtrack or revisit previously-visited nodes).

MATCH (start:station), (end:station)
WHERE start.name='NBW' AND end.name='RD'
CALL apoc.path.spanningTree(start, {terminatorNodes:[end], limit:1,
  relationshipFilter:'has_platform>|can_board>|goto>|can_alight>|<has_platform'}) YIELD path
RETURN path 

Your query is directed --> and not all of the relationships between your two stations run in the same direction. If you remove the relationship direction you will get a result.

Then once you have a result I think something like this could get you pointed in the right direction on extracting the particular details from the resulting path once you get that working.

Essentially I am assuming that everything you are interested in is in your path that is returned you just need to filter out the different pieces that are returned.

As @InverseFalcon points out this query should be limited in a larger graph or it could easily run away.

MATCH p = (a:Station)-[r:Goto|can_board|can_alight|has_platfrom*0..]-(c:Station) 
WHERE (a.name='NBW') 
AND c.name='THT' 
RETURN filter( n in nodes(p) WHERE 'Platform' in labels(n)) AS Platforms

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM