bkramer
bkramer

Reputation: 49

Neo4j - Check if sequential path exists

I want to see if a path exists for a graph, given a list of sequential properties to search for. The list can be of variable length.

This is my most recent attempt:

WITH ['a', 'b', 'c', 'd'] AS search_list // can be any list of strings
// FOREACH (i IN range(search_list) |
//     MATCH (a:Node {prop:i})-->(b:Node {prop:i+1}))
// RETURN true if all relationships exist, false if not

This solution doesn't work because you can't use MATCH in a FOREACH. What should I do instead?

Upvotes: 0

Views: 1341

Answers (2)

stdob--
stdob--

Reputation: 29172

You can try to build a query manually for the match entire path and execute it using the function apoc.cypher.run:

WITH ['a', 'b', 'c', 'd'] AS search_list
WITH search_list,
     'MATCH path = ' +  
     REDUCE(c = '', i in range(0, size(search_list) - 2) | 
            c + '(:Node {prop: $props[' + i + ']})-->'
     ) +
     '(:Node {prop: $props[' + (size(search_list) - 1)  +']}) ' +
     'RETURN count(path) as pathCount' AS cypherQuery
CALL apoc.cypher.run(cypherQuery, {props: search_list}) YIELD value
RETURN CASE WHEN value.pathCount > 0 
            THEN true 
            ELSE false 
       END AS pathExists

Upvotes: 2

cybersam
cybersam

Reputation: 66989

Assuming you pass the list of property values in a $props parameter and the length of that list is 4, this query will first search for all paths of length 4 that have the desired start and end nodes (to narrow down the candidate paths), and then filter the interior nodes of the paths:

MATCH p=(a:Node {prop: $props[0]})-[*4]->(b:Node {prop: $props[-1]})
WITH p, NODES(p)[1..-2] AS midNodes
WHERE ALL(i IN RANGE(1, SIZE(midNodes)) WHERE midNodes[i-1] = $props[i])
RETURN p;

To increase efficiency, you should create an index on :Node(prop) as well.

If this query returns nothing, then there are no matching paths.

Upvotes: 0

Related Questions