Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
04-25-2022 02:51 PM
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?
04-25-2022 05:09 PM
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
04-25-2022 11:14 PM
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
All the sessions of the conference are now available online