lo tolmencre
lo tolmencre

Reputation: 3934

Cypher: Remove Nodes from Path

I want to find a path (in this case the entire database), where there is a :B node that has no incoming :s-edge and then remove all the :Bs of the path.

This is my test database:

MERGE (B1:B {name:"B1"})-[:t]->(B2:B {name:"B2"})-[:t]->(B3:B {name:"B3"})-[:t]->(B4:B {name:"B4"})-[:t]->(B5:B {name:"B5"})-[:t]->(C1:D {name:"D1"})
MERGE (A1:A {name:"A1"})-[:s]->(B1)
MERGE (A2:A {name:"A2"})-[:s]->(B2)
MERGE (A3:A {name:"A3"})-[:s]->(B4)
MERGE (A5:A {name:"A5"})-[:s]->(B5)

5)

enter image description here

The query I tried last is this, but it throws an error:

MATCH p=(n:A)-[*] ->(o:B)-[:t*]->(m:D)  
WITH NODES(p)[1..-1] AS Pspace_nodes, o, p
MATCH o WHERE NOT ()-[:s]->(o)
FOREACH (n IN Pspace_nodes| MATCH n-[*]-() DELETE n , r)

Error message:

py2neo.cypher.error.statement.InvalidSyntax: Invalid use of MATCH inside FOREACH (line 4, column 29 (offset: 143))
"FOREACH (n IN Pspace_nodes| MATCH n-[*]-() DELETE n , r)

How do I express this in a valid fashion?

Upvotes: 0

Views: 998

Answers (1)

cybersam
cybersam

Reputation: 66989

[EDITED]

This might work for you:

MATCH p=(:A)-[r*]-(:D)
WHERE ANY (x IN NODES(p)[1..-1] WHERE x:B AND NOT ()-[:s]->(x))
WITH REDUCE(s =[], y IN NODES(p)[1..-1]| CASE WHEN y:B THEN s + y ELSE s END ) AS todo
UNWIND todo AS node
WITH DISTINCT node
DETACH DELETE node;

In a larger DB, this can take a long time to run because the MATCH specifies a variable-length path. If this is a problem, you should use a reasonable upper bound (e.g., [r*..5]).

The WHERE clause filters for paths with a B node with no incoming :s relationship. The REDUCE function collects all the B nodes in the path. The UNWIND puts each B node in a separate row. The DISTINCT removes all duplicate nodes so that the deletion attempt will not try to delete a node twice (which causes neo4j to generate an error). The DETACH DELETE clause will not only delete those B nodes but also all their relationships (since you are not allowed to delete a node without also doing that).

Upvotes: 1

Related Questions