How to Exclude nodes from Path with Cypher

I'm stuck writing a Cypher query that would allow me to find all nodes which their code are NOT included in a given list. I've tried searching for pattern negation, node negation, exclude in path with no success.

Let's assume I have a list of codes (even though this list one has 1 element): ["1V2ZG"]

I'd like to build a Cypher query that would return every child of ARNOG node which is NOT in the above list.

This is the starting graph:


The graph response I want:

I'd like the query to return only the "ARNOG" node if the code list contains BOTH of its children ("Y6JPG", "1V2ZG") OR return No results
image
The query I'm using is returning all nodes which is not what I want:

MATCH 
(excl:Client)<-[:PARENT_OF*]-(n:Client:Group),
path=(b:BaseHierarchy)-[:INCLUDES]->(n)-[:PARENT_OF*]->(inc:Client) 

WHERE excl.code IN ['1V2ZG']  AND n.code = 'ARNOG' 
WITH b,
nodes(path) as nodes, relationships(path) as relationships 
RETURN b,
apoc.coll.toSet(apoc.coll.flatten(collect(relationships))) as relationships,
apoc.coll.toSet(apoc.coll.flatten(collect(nodes))) as nodes;

Look out for pattern comprehension

Sorry I don't have that much time but it's a good start:

MATCH (b:Base)-[:INCLUDES]->(n)
RETURN [(n)-[:PARENT_OF*]->(sn) WHERE sn.code IN [list] | sn ] AS nodes

1 Like

It sounds like something known...

It seems to work until you try to get the path around 'n'. I don't understand why, but I get the same result.
May be you can have a try in isolating the 'n' in a first match

MATCH (b:BaseHierarchy)-[:INCLUDES]-> (client:Client)->[:PARENT_OF]-(n:Client:Group)
WHERE client.code = 'ARNOG' and not n.name in ['1V2ZG', '1V3ZG']
WITH incl, client, n
MATCH path = (b)-[:INCLUDES]->(client)->[:PARENT_OF]-(n)->[:PARENT_OF*]-(inc:Client:Group)
WITH b, nodes(path) as nodes, relationships(path) as relationships 
RETURN b,
apoc.coll.toSet(apoc.coll.flatten(collect(relationships))) as relationships,
apoc.coll.toSet(apoc.coll.flatten(collect(nodes))) as nodes;

Pay attention that this solution assumes that there is at least one 'inc' after 'n', which seems to match your case.

How do I include only nodes NOT in the given code list?

Thanks

Hi Benoit, I just remember you answered my previous question which was almost exactly like this one.

The thing is if the given list contains both codes ("1V2ZG" and "Y6JPG") the returning graph contains both of them, which is not what I want. If the list only contains 1 of them, the result is what I expect, containing the OTHER element.

Thanks

Oops, indeed my proposition was the opposite.
Slight modification, the list comprehension will return a list of the nodes who fits with your criteria. I know it's not a complete answer but it's almost.

MATCH (b:Base)-[:INCLUDES]->(n)
RETURN [(n)-[:PARENT_OF*]->(sn) WHERE NOT sn.code IN [list] | sn ] AS nodes

You can also use the FOREACH clause, to traverse and tag them with a SET clause so you can process them differently later on in future query.