Search code examples
neo4jcypher

In Neo4J, while removing a relationship from a node, how do you also delete the node itself it doesn't have other relationships?


While removing a relationship, I'd like to understand if a node will be orphan and, if so, delete the node aswell.

example input graph:

(a)-[r1]-(b)-[r2]-(c)-[r3]-(d)

expected graph after removing relationship r3: (d) would be orphan, so delete it.

(a)-[r1]-(b)-[r2]-(c)

expected graph after removing relationship r2: two splitted graphs, no node deleted.

(a)-[r1]-(b)   
(c)-[r3]-(d)

Is it possible to achieve that in cypher?


Solution

  • If you want to delete relationships together with their then orphaned nodes individually try first fetching the start and end nodes for the relationship you are about to delete, delete the relationship, then test if the nodes are 'orphaned' and conditionally delete them. You can do this by putting the start/end nodes in a collection, filter the collection on NOT n--() as a predicate, then delete the nodes in the filtered collection in a FOREACH loop.

    MATCH (a {name:"Federico"})-[r1]-(b)-[r2]-(c)-[r3]-(d)
    WITH r3, [startNode(r3), endNode(r3)] as ns
    DELETE r3
    WITH [n IN ns WHERE NOT n--()] as orphans
    FOREACH (n IN orphans | DELETE n)
    

    If you want to delete several relationships at once you can try binding your pattern as a path

    MATCH path=(a {name:"Federico"})-[r1]-(b)-[r2]-(c)-[r3]-(d)
    

    then after you have deleted some relationships

    DELETE r1, r3
    

    you can filter all nodes in the path and delete the orphans as above

    WITH [n IN nodes(path) WHERE NOT n--()] as orphans
    FOREACH (n IN orphans | DELETE n)
    

    As long as the relationships you delete are in the path, any orphaned nodes they leave behind will also be deleted.

    (I can't test these queries at the moment but I think I got the grammar right.)