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?

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
```

1 Like

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
```