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.

mrksph
Node Clone

Hi there,

We're using Neo4j 4.2 Enterpise Edition.

In our app we have a query like this:

MATCH path=(b:BaseHierarchy)-[]->(n:Group)-[:PARENT_OF*]->(c:Client) 
WHERE n.code = 'XXXXX' AND c.code IN ["AAA","BBB","CCC","DDD"]
WITH collect(path) as paths, b 
WITH b, 
reduce(a=[], node in reduce(b=[],c in [aa in paths | nodes(aa)] | b + c) | case when node in a then a else a + node end) as nodes, reduce(d=[], relationship in reduce(e=[],f in [dd in paths | relationships(dd)] | e + f) | case when relationship in d then d else d + relationship end) as relationships 
RETURN b, relationships, nodes;

The query runs very fast and I get the result I expect. The goal of this query is to get a node and only SOME of its child (the ones specified in the List).

After this query runs, we build its "negated" version which is something like this:

MATCH path=(b:BaseHierarchy)-[]->(n:Group)-[:PARENT_OF*]->(c:Client) 
WHERE n.code = 'XXXXX' AND (NOT c.code IN ["AAA","BBB","CCC","DDD"]
WITH collect(path) as paths, b 
WITH b, 
reduce(a=[], node in reduce(b=[],c in [aa in paths | nodes(aa)] | b + c) | case when node in a then a else a + node end) as nodes, reduce(d=[], relationship in reduce(e=[],f in [dd in paths | relationships(dd)] | e + f) | case when relationship in d then d else d + relationship end) as relationships 
RETURN b, relationships, nodes;

Note: Please do not mind the reduce, it's there because we're using Spring Data Neo4j and we need it to make things work (we'd have to change versions which isn't feasible to do right now).

The query is intended to get all nodes that aren't the ones I selected previously, this is the first approach that worked for us.

In this case, the query is VERY slow, sometimes depending on the subgraph it doesn't even finish.
I'm aware that one of the reasons this negated version of the query isn't performant because the WHERE clause isn't supposed to be used like this as it is evaluated at every node/level.

After researching a bit, I came up with this article Performing pattern negation to multiple nodes - Knowledge Base where it teaches how to use pattern negation but I can't make it work with my query.

Would someone give me a hand on how to proceed?

Thanks

EDIT: I should say that the :Group node has a very large subgraph under it, over 300 direct children and these children may each have more children N times

Comments
mrksph
Node Clone

This one looks good:

MATCH (excluded:Client)
WHERE excluded.code in ["AAA","BBB","CCC","DDD"]
WITH collect(excluded) as excluded
MATCH path=(b:BaseHierarchy)-[]->(n:Group)-[:PARENT_OF*]->(c:Client) 
WHERE n.code = 'XXXX'
WITH excluded, path, b, collect(c) as clients, n
WHERE NONE (c in clients where c in excluded)
RETURN path, b, n, clients

But if I add the reduce part, the query never finishes....

MATCH (excluded:Client)
WHERE excluded.code in ["AAA","BBB","CCC","DDD"]
WITH collect(excluded) as excluded
MATCH path=(b:BaseHierarchy)-[]->(n:Group)-[:PARENT_OF*]->(c:Client) 
WHERE n.code = 'XXXX'
WITH excluded, collect(path) as paths, b, collect(c) as clients, n
WHERE NONE (c in clients where c in excluded)
WITH b,
reduce(a=[], node in reduce(b=[],c in [aa in paths | nodes(aa)] | b + c) | case when node in a then a else a + node end) as nodes, reduce(d=[], relationship in reduce(e=[],f in [dd in paths | relationships(dd)] | e + f) | case when relationship in d then d else d + relationship end) as relationships 
RETURN b, relationships, nodes;

Version history
Last update:
‎05-06-2021 06:12 AM
Updated by:
Contributors