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.

Unwind and match only if list is non-empty?

I have a situation where I am looking for paths of the form (:A|B)-[:REL]->(A|B)-[:REL]-> ... -[:REL]->(A|B).

That is, the paths go through nodes with label A or B.

Specifically, if the path is only A nodes, then it can be included in the result set.
However, if the path contains some B nodes, then they must be connected to a particular root node. If the path includes any B nodes that aren't connected to the root, the path shouldn't match.

If have set up this query something like this (REL edges can only exist between nodes labelled A or B);

MATCH p = (x)-[:REL*1..]->(y)
with x, y, [n in nodes(p) where 'B' in labels(n)] as b_nodes
unwind b_nodes as n
match (n)-[*]->(:ROOT)
return x, y

This works, except in the case of all A nodes. What I want to do is skip the unwrap & second match if b_nodes is [].

Is this possible, or is there a better way of achieving this?

2 REPLIES 2

Try this, I think it works. I had to include the 'size(b_nodes) > 0' because the 'all' predicate returns true for an empty list, even if the where predicate is false.

I included label conditions for x and y to eliminate paths being returned where x or y could be root nodes in the case of paths with 'B' nodes.

match p = (x)-[:REL*1..]->(y)
where (x:A or x:B) and (y:A or y:B)
with x, y, nodes(p) as all_nodes, [n in nodes(p) where 'B' in labels(n)] as b_nodes
where all(n in all_nodes where 'A' in labels(n)) 
or (size(b_nodes) > 0 and all(n in b_nodes where exists( (n)-[*]->(:ROOT) )))
return x, y

Thank you! I was getting myself in a total muddle.

You actually made me realise I could simplify your example a bit;

match p = (x)-[:REL*1..]->(y)
where (x:A or x:B) and (y:A or y:B)
with x, y, [n in nodes(p) where 'B' in labels(n)] as b_nodes
where size(b_nodes) = 0 or all(n in b_nodes where exists( (n)-[*]->(:ROOT) )))
return x, y