cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

Best path algorithm with relationship preference

Hello !

I'd like to know if there is a way to find a "best path" with only a starting node and relationships preferences.

For exemple, if we have this initial cypher :

CREATE (a {title: 'a'})-[:USES]->(b {title: 'b'})-[:USES]->(c {title: 'c'})<-[:SWITCH]-(d {title: 'd'})<-[:USES]-(e {title: 'e'})-[:SWITCH]->(b) RETURN *

I'd like, starting from a node, find any length path of USES relationships, but stop at first SWITCH incoming relationship.

With this example, starting from node a, I'd like to find as result :

(a)-[:USES]->(b)<-[:SWITCH]-(e)

instead of :

(a)-[:USES]->(b)-[:USES]->(c)
(a)-[:USES]->(b)-[:USES]->(c)<-[:SWITCH]-(d)

Is there any existing algorithm allowing relationship preference ? I didn't find any. I looked at shortestPath, A* and Minimum Spanning Tree (Path Finding Algorithms - Developer Guides) but they don't exactly fit my need.
I would even prefer a standard cypher syntax instead of calling a function, but I couldn't find any.

Any help will be appreciated !

Thanks,

3 REPLIES 3

did you try

match path = (a)-[:USES*]->(b)<-[:SWITCH]-(e)
return path order by length(path) limit 1

Thank you for your reply.

The fact, which I didn't mention, is that there could be no SWITCH relactionship (and no USES also). With your suggest, I could enhance one of my last attempt which was :

MATCH (a) 
OPTIONAL MATCH p=(a)-[:USES*]->(b) 
OPTIONAL MATCH (s)-[:SWITCH]->(b) 
RETURN a,p,s

to obtain :

MATCH (a) 
OPTIONAL MATCH p=(a)-[:USES*]->(b) 
OPTIONAL MATCH (s)-[:SWITCH]->(b) 
RETURN a,p,s 
ORDER BY length(p) LIMIT 1

The point is on the ORDER BY and LIMIT clauses as you suggested.
It doesn't work as expected because p doesn't stop at first SWITCH relationship since this one is MATCH as optional.

This one may have the expected behavior :

MATCH (a) 
OPTIONAL MATCH p=(a)-[:USES*]->(b)<-[:SWITCH]-(s) 

CALL apoc.when(p IS NOT NULL, 'RETURN p', 'MATCH p=(a)-[:USES*]->(b) RETURN p', {p: p, a: a}) 
YIELD value 

RETURN a, value.p, s
ORDER BY length(p) 
LIMIT 1;

But it needs apoc and I have to duplicate any WHERE condition in both the first OPTIONAL MATCH and the elseQuery. (not shown in this exemple)

Is there any sexier query to achieve this ?