Search code examples
databaseneo4jcyphergraph-databasescypher-3.1

neo4j delete a node in linked list


I have a list of posts that belong to a user. The posts are structured as linked list that belongs to a given user.

I am having deleting the a given node while preserving the data structure.

Here is an illustration of the structure.

enter image description here

In my list attempt I have written the query below, however it does not work since the MATCH does not return anything in the sub-queries.

I thought about using OPTIONAL MATCH in the sub-queries, however that results in exceptions.

MATCH(node:Post)
WHERE ID(node) = 2749
WITH node
MATCH(user:User)-[:OWNS]->(node)-[:PREV]->(nextNode:Post)
CREATE(user)-[:OWNS]->(nextNode)
WITH node
MATCH(prevNode:Post)-[:PREV]->(node)-[:PREV]->(nextNode:Post)
CREATE(prevNode)-[:PREV]->(nextNode)
WITH node
DETACH DELETE node

I assumed that if a pattern in a sub-query fails than the rest of the sub-query will be skipped and the next sub-query will still execute. But it seems that the whole thing does not get executed.

How do we perform something like in the following in sub-queries without halting the execution.

IF pattern matches
THEN 
   CREATE EDGE 
IF pattern matches
THEN
   Do something else

Solution

stdob--'s answer is the closest to the right solution, however it fails to delete nodes at the end of the list and throws an exception as it does not check if the nextNode exists in the second FOREACH statement.

It needed tweaking to work:

MATCH(node:Post) WHERE ID(node) = 2813

OPTIONAL MATCH (user:User)-[:OWNS]->(node)
OPTIONAL MATCH (node)-[:PREV]->(nextNode:Post)
OPTIONAL MATCH (prevNode:Post)-[:PREV]->(node)

FOREACH (ith in CASE 
    WHEN user IS NOT NULL AND nextNode IS NOT NULL 
    THEN [1] 
    ELSE [] 
    END | CREATE (user)-[:OWNS]->(nextNode) 
)

FOREACH (ith in CASE WHEN 
    prevNode IS NOT NULL AND nextNode IS NOT NULL 
    THEN [1] ELSE [] 
    END | CREATE (prevNode)-[:PREV]->(nextNode)
)

DETACH DELETE node

Solution

  • You can use combination of OPTIONAL MATCH, FOREACH and CASE:

    MATCH(node:Post) WHERE ID(node) = 2749
    
    OPTIONAL MATCH (user:User)-[:OWNS]->(node)
    OPTIONAL MATCH (node)-[:PREV]->(nextNode:Post)
    OPTIONAL MATCH (prevNode:Post)-[:PREV]->(node)
    
    FOREACH (ith in CASE WHEN 
                         NOT user IS NULL AND 
                         NOT nextNode IS NULL 
                    THEN [1] ELSE [] END |
        CREATE (user)-[:OWNS]->(nextNode) 
    )
    
    FOREACH (ith in CASE WHEN 
                         NOT prevNode IS NULL AND
                         NOT nextNode IS NULL
                    THEN [1] ELSE [] END |
        CREATE (prevNode)-[:PREV]->(nextNode)
    )
    
    DETACH DELETE node
    

    Update: Also you can use the procedure apoc.do.when from the apoc.library for the conditional query execution.