Why don't these Cypher queries do the same thing? - neo4j

I am matching a full path, deleting the last node and then walking back up the nodes to delete any that have no downward relationships.
This query does what I want:
MATCH (t:type)-[:HAS]->(m:model)-[:HAS]-(r:region)-[:HAS]-(p:param)-[:HAS]-(i:init { value: 1613044800})-[init_has:HAS]-(u:{url: 'http://something2.png'})
DELETE init_has, u
WITH i,p,r,m,t
MATCH (i) WHERE NOT (i)-[:HAS]->()
DETACH DELETE i
WITH p,r,m,t
MATCH (p) WHERE NOT (p)-[:HAS]->()
DETACH DELETE p
WITH r,m,t
MATCH (r) WHERE NOT (r)-[:HAS]->()
DETACH DELETE r
WITH m,t
MATCH (m) WHERE NOT (m)-[:HAS]->()
DETACH DELETE m
WITH t
MATCH (t) WHERE NOT (t)-[:HAS]->()
DETACH DELETE t
But this query only deletes the first node in the in the WITH statement, i:
MATCH (t:type)-[:HAS]->(m:model)-[:HAS]-(r:region)-[:HAS]-(p:param)-[:HAS]-(i:init { value: 1613044800})-[init_has:HAS]-(u:{url: 'http://something2.png'})
DELETE init_has, u
WITH [i,p,r,m,t] AS parents
UNWIND parents AS parent
WITH parent
MATCH (parent) WHERE NOT (parent)-[:HAS]->()
DETACH DELETE parent
It leaves the node p, which does not have any downward relationships. Why are these queries different? Can I somehow modify the second query to correctly iterate through these nodes and delete them if they have no downward relationships?

I am not exactly sure what seems to be the problem. I can give you hint how you can improve your query a bit. When you want to do filtering on later steps, you don't have to use another MATCH statement. In your case:
MATCH (t:type)-[:HAS]->(m:model)-[:HAS]-(r:region)-[:HAS]-(p:param)-[:HAS]-(i:init { value: 1613044800})-[init_has:HAS]-(u:{url: 'http://something2.png'})
DELETE init_has, u
WITH [i,p,r,m,t] AS parents
UNWIND parents AS parent
WITH parent
WHERE NOT (parent)-[:HAS]->()
DETACH DELETE parent
I am not sure if this will solve your problem though. The query looks fine so it is hard to say whats wrong without an example.

Related

Neo4j node/relation inconsistencies

When fetching or when I try to delete a specifc node like
MATCH (p)
where ID(p)=79259223
OPTIONAL MATCH (p)-[r]-()
//drops p's relations
DELETE r,p
I get the following error
While loading relationships for Node[79259223] a Relationship[87331456] was encountered that had startNode: 80312215 and endNode: 83719851, i.e. which had neither start nor end node as the node we're loading relationships for
I also run the ConsistencyChecker what resulted in a big list of inconsistencys. However how can you fix these inconsistencys? I can not delete the nodes for instance
Here is a possible way to "fix" an occurrence of this error. Unfortunately, it is a fairly manual approach that has to be used for every node that encounters the same problem.
Before you delete the node, you can try to delete the inconsistent relationship by its native neo4j ID. For example:
MATCH ()-[r]->()
WHERE ID(r) = 87331456
DELETE r;
NOTE: Before deleting that relationship, you should first try to take a look at it (e.g., replace DELETE WITH RETURN) to understand what you are planning to delete. You may want to do something else first or instead.
If that deletion works, then try to delete the node again, as follows:
MATCH (p)
WHERE ID(p) = 79259223
DETACH DELETE p;
Notice that I use the DETACH DELETE syntax, which will attempt to delete all the relationships for the specified node.

How to delete all child nodes and relationships using single query in Neo4j.?

I have a tree like node structure in my Neo4j DB. When I delete particular node I want to delete all child nodes and relationships related to that node.
Consider node structure generated by below query,
merge (p1:Person{nic:'22222v'})-[r1:R1]->(p2:Person{nic:'33333v'})
merge(p1)-[r2:R2]->(p3:Person{nic:'44444v'})
merge(p2)-[r3:R3]->(p3)
merge (p3)-[r4:R4]->(p4:Person{nic:'55555v'})
merge(p4)-[r5:R5]->(p5:Person{nic:'66666v'})
return r1,r2,r3,r4,r5
If I input node(nic:44444v) it should delete node(nic:44444v),node(nic:55555v),node(nic:66666v
), relationship(r2),relationship(r3),relationship(r4) and relationship(r5)
You can use multiple depth relationships and delete the nodes :
MATCH (n:Person {nic:'44444v'})-[*0..]->(x)
DETACH DELETE x
The 0.. depth definition will embed the n identifier in the x nodes and thus will handle the case where the person doesn't have children nodes.
Alternative syntax for oldier neo4j versions :
MATCH (n:Person {nic:'44444v'})-[*0..]->(x)
OPTIONAL MATCH (x)-[r]-()
DELETE r, x

Cypher delete a node and all related nodes if they don't have a further relations

To keep my database clean from orphaned nodes, I want to delete a Node - identified by a given property value - and every related Node that does not have any other related nodes.
Is that possible? Currently I'm doing this:
MATCH (poi:PointOfInterest)-[r]-(allRelatedNodes)
WHERE poi.id="X007"
DETACH DELETE poi, r, allRelatedNodes;
But that deletes all related Nodes including the ones that would be connected to other Nodes if they weren't deleted.
Is there a way to delete a Node and all related Nodes that don't have relations to other Nodes?
Edit by the author:
The marked answer is correct. I finally solved my problem with
MATCH (poi:Node)-[r*0..1]-(allRelatedNodes)
WHERE poi.name = "A"
AND size((allRelatedNodes)--()) < 2
DETACH DELETE poi, allRelatedNodes;
If you make the allRelatedNodes match optional and ensure allRelatedNodes only have a single relationship to poi then you should be able to delete only the ones attached to X007 if they exist. Also, you don't need to specify r in the delete statement as DETACH takes care of that.
MATCH (poi:PointOfInterest)
WHERE poi.id = "X0007"
WITH poi
OPTIONAL MATCH (poi)-[r]-(allRelatedNodes)
WHERE size((allRelatedNodes)--()) = 1
DETACH DELETE poi, allRelatedNodes
Using Neo4j 3.0 and starting with the following graph...
And executing a close facsimile of the above query (listed below)...
MATCH (poi:Node)-[r]-(allRelatedNodes)
WHERE poi.name = "A"
AND size((allRelatedNodes)--()) = 1
DETACH DELETE poi, allRelatedNodes
I am left with this graph.
If that does not delete it all in one query you could use this instead and that should definitely take care of it.
MATCH (poi:PointOfInterest)-[r]-(allRelatedNodes)
WHERE poi.id = "X007"
AND size((allRelatedNodes)--()) = 1
WITH poi, collect(allRelatedNodes) as allRelatedNodes
DETACH DELETE poi
WITH allRelatedNodes
UNWIND allRelatedNodes as node
DELETE node

How to delete nodes in reverse order in neo4j

I have a database with nodes like
(u : Update)-[:HAS_COMMENT]->(latest_comment:Comment)-[:NEXT]->(c1: Comment)->(c2: Comment)
And so on.. Each Comment node has a relation with User node
(c : Comment)<-[:HAS_COMMENTED]-(u : User).
Now I have to delete the update node so with this all the comment nodes should be deleted and relation between User and Comment should also be deleted.
The solution that came to my mind is to traverse from last Comment node and start deleting relation with User node and delete Comment node and "NEXT" relation with the previous comment node. I am facing the problem to write such query.
Can someone help me with this?
Use a variable length path in an OPTIONAL MATCH statement to match on all Comments in the path (chained together with :NEXT relationships) then use DETACH DELETE to delete the nodes and relationships:
MATCH (u:Update {name: "UpdateToDelete"})-[:HAS_COMMENT]->(c:Comment)
OPTIONAL MATCH (c)-[:NEXT*]->(r:Comment)
DETACH DELETE u,c,r
DETACH DELETE will remove nodes and any relationships connected to the nodes being deleted.
Here is a Neo4j console to test.
Edit
The DETACH DELETE statement was added in Neo4j version 2.3. To accomplish this without using DETACH DELETE try this query:
MATCH (u:Update {name: "UpdateToDelete"})-[hc:HAS_COMMENT]->(c:Comment)
MATCH (c)-[n:NEXT*0..]->(r:Comment), (r)<-[h:HAS_COMMENTED]-(:User)
FOREACH (x IN n | DELETE x)
DELETE r,u,hc,c,h
The key difference is that without using DETACH DELETE we have to match on each relationship that connects a given node and delete those relationships when we delete the node. Since we have a variable length path (Comments connected by an arbitrary number of NEXT relationships) we can use the FOREACH function to iterate through the collection of NEXT relationships and delete them as we delete the Comment node(s).

What's the Cypher script to delete a node by ID?

In SQL:
Delete From Person Where ID = 1;
In Cypher, what's the script to delete a node by ID?
(Edited: ID = Neo4j's internal Node ID)
Assuming you're referring to Neo4j's internal node id:
MATCH (p:Person) where ID(p)=1
OPTIONAL MATCH (p)-[r]-() //drops p's relations
DELETE r,p
If you're referring to your own property 'id' on the node:
MATCH (p:Person {id:1})
OPTIONAL MATCH (p)-[r]-() //drops p's relations
DELETE r,p
The cleanest sweep for a node with id "x" is
MATCH (n) where id(n) = x
DETACH DELETE n
https://neo4j.com/docs/cypher-manual/current/clauses/delete/#delete-delete-a-node-with-all-its-relationships
https://neo4j.com/docs/cypher-manual/current/functions/scalar/#functions-id
Old question and answered, but to delete node when it has relationships, use DETACH
MATCH (n) where ID(n)=<your_id>
DETACH DELETE n
or otherwise you get this:
Neo.ClientError.Schema.ConstraintValidationFailed: Cannot delete node<21>, because it still has relationships. To delete this node, you must first delete its relationships.
It's like SQL's CASCADE
When the node is a orphan.
Start n=node(1)
Delete n;
Following the link provided by #saad-khan, here's an example for getting the nodes and relationships ids.
The code below shows the ids, so you can make sure that you're deleting everything related to the given ID.
MATCH (node)-[relation:HAS]->(value)
where ID(node)=1234
RETURN ID(instance), ID(value), ID(r)
Ps.: ":HAS" is an example of an relationship.

Resources