cancel
Showing results for 
Search instead for 
Did you mean: 

Validating Shortest-Path status inside another Path

nima
Node Link

Problem

MERGE (Z1:Z {z_id : 'z1'})-[:HAS_CHILD]->(z2:Z {z_id : 'z2'})-[:HAS_CHILD]->(z3:Z {z_id : 'z3'})-[:HAS_CHILD]->(z4:Z {z_id : 'z4'})-[:HAS_CHILD]->(z5:Z {z_id : 'z5'})

Create (x1:X {x_id: 'x1'})-[:HAS_OBJ]->(y1: Y {y_id: 'y1'})-[:HAS_OBJ]->(x2:X {x_id: 'x2'})-[:HAS_OBJ]->(y2: Y {y_id: 'y2'})-[:HAS_OBJ]->(x3:X {x_id: 'x3'});

MATCH (y:Y {y_id: 'y1'}),(z:Z {z_id: 'z2'})  WITH y,z CREATE (y)-[:HAS_Z {status: true}]->(z);
MATCH (y:Y {y_id: 'y2'}),(z:Z {z_id: 'z2'})  WITH y,z CREATE (y)-[:HAS_Z {status: true}]->(z);
MATCH (y:Y {y_id: 'y2'}),(z:Z {z_id: 'z4'})  WITH y,z CREATE (y)-[:HAS_Z {status: false}]->(z);

  • Given: starNode (of type X), endNode (of type X) and z:Z node as input,
  • Find: All available paths between startNode to endNode
  • Condition: When all shortest-paths between all Y nodes (in the returned paths) to the given Z node are healthy (status=true)

Examples:

Say, in the example above & considering x1 as startNode & x2 s endNode ...

  • given Z: z1 there should be no path -> since there's no way to rearch z1 from any of Y Nodes
  • given Z: z3: there should be a valid path, since the shortest-paths available for all y nodes to Z nodes are in a healthy state (y1->z2-_z3 & y2->z2->z3)
  • given Z: v5: there should be no path -> Although the shortest path from y1 to z5 is in the healthy state (y1->z2->z3->z4->z5), but the shortest path from Y2 to z6 is not healthy (y2->z4->z5), since the status of y2->z4 is false

This was the first version of my Cypher query, but it's not working as expected (returns path in case of z: z5)

MATCH (z:Z) WHERE z.z_id = 'z5'
WITH z MATCH (start:X) WHERE start.x_id = 'x1'
with z,start MATCH (end:X) WHERE end.x_id = 'x3'
WITH z,start,end
MATCH p=(start)-[:HAS_OBJ*1..]->(y:Y)-[:HAS_OBJ*1..]->(end), p2=shortestPath((y)-[*1..]->(z))
WHERE ALL (
    r in relationships(p2) WHERE 
         type(r)= 'HAS_CHILD' OR (type(r) = 'HAS_Z' AND r.status = true)
)
return p

Thanks in advance

1 REPLY 1

nima
Node Link

I think I found the solution (by adding one extra line: WITH p,p2 between the last MATCH and WHERE clause) - letting the shortest-path function first find the existing shortest-path available (& not searching for a (shortest-)path which is compatible with predicate)

MATCH (z:Z) WHERE z.z_id = 'z5'
WITH z MATCH (start:X) WHERE start.x_id = 'x1'
with z,start MATCH (end:X) WHERE end.x_id = 'x3'
WITH z,start,end
MATCH p=(start)-[:HAS_OBJ*1..]->(y:Y)-[:HAS_OBJ*1..]->(end), p2=shortestPath((y)-[*1..]->(z))
WITH p,p2
WHERE ALL (
    r in relationships(p2) WHERE 
         type(r)= 'HAS_CHILD' OR (type(r) = 'HAS_Z' AND r.status = true)
)
return p,p2
Nodes 2022
Nodes
NODES 2022, Neo4j Online Education Summit

On November 16 and 17 for 24 hours across all timezones, you’ll learn about best practices for beginners and experts alike.