How to delete followed nodes by length variable - neo4j

I have a tree structure, like node(8) has two children node(13) and node(14).
How can I delete all children when I delete node(8) by cyhper.
I write cypher like this:"
START r=node(8) MATCH r-[:children*0..]-> d With d Match d-[x]-() Delete d,x"
It should work, but actually it only delete node(8) and get some error.
I find that actually it's trying to delete a collection like this.
---d-------------------r
Node(8)----------Rel(16)
Node(8)----------Rel(17)
Node(9)----------Rel(16)
Node(10)---------Rel(17)
And after cyhper delete first Node(8), it try to delete Node(8) for second time and get error because it doesn't exist anymore.
It's wired cause when I write cypher like this:
"START r=node(8) MATCH r-[:children*0..]-> d Return d"
It returns:
---d---
Node(8)
Node(8)
Node(9)
Node(10)
And it's right. But as we know, I can't delete them with relationship on them, so I need to write a cypher with "WITH":
"START r=node(8) MATCH r-[:children*0..]-> d With d Match d-[x]-() Return d,x"
And it get the wrong result again.
---d-------------------r
Node(8)----------Rel(16)
Node(8)----------Rel(17)
Node(9)----------Rel(16)
Node(10)---------Rel(17)
Can anyone help me? It's really depressed.
I really like neo4j, but I find the "Delete" part is such tough.
Why not just use "Force Delete" and make Neo4j to auto delete relationships just like this:
"START r=node(8) MATCH r-[:children*0..]-> d FORCE DELETE d"
And btw, why can't use distinct in "Delete" part?

There was a bug in an earlier neo4j version--I don't remember which. Which version are you using? You should be able to do this sort of query without an error about a node existing.
I also agree that this syntax should be easier. This is how I got it to work.
start n=node(8) // start at the node you want to delete
match n-[r:children*0..]->m, n-[anyothers?]-() // find your pattern to delete, and find any other relationships coming off of n (inbound/non :children)
foreach(x in r: delete x) // delete all the relationships for children
delete m, n, anyothers; // delete the nodes and any other relationships

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.

Unable to load NODE with id

I recently upgraded my Neo4j database to v. 3 (3.0.6). Since then I am having trouble when trying to delete nodes with Cypher. This is a new problem since the upgrade. They Cypher query is:
MATCH (p) WHERE id(p) = 83624
OPTIONAL MATCH (p)-[r]-(n)
OPTIONAL MATCH (p)-[r2]-(n2)
WHERE NOT ('Entity' in labels(n2))
DELETE r, r2, p, n2
This now results in the error Unable to load NODE with id 83624
The exact query with RETURN instead of DELETE returns the node. I've also tried swapping out DELETE with DETACH DELETE of the nodes, but that gives me the same error.
It looks like this question has been asked before but without a solution. Any idea what is causing this error?
I'm a little confused by this query. Both of your optional matches are identical, in that they will match to any relationship to any node connected to p.
Let me make sure I understand what you're trying to do: Find a node by ID, then delete that node along with any connected node that is not an Entity (as well as the relationships connecting them). Is that right?
If so, this query might work better:
MATCH (p) WHERE id(p) = 83624
OPTIONAL MATCH (p)--(n)
WHERE NOT n:Entity
DETACH DELETE n
DETACH DELETE p
Detaching a node deletes all relationships connected to that node, and you can only delete a node that has zero relationships.
Also, just to note, it's not a good idea to use the internal ids for uniquely identifying nodes. It's recommended to use your own unique IDs instead, and create unique constraints on that property for that label.

Neo4j cypher: Deleting a collection of relationships

I think this may be a bug, however, when deleting a collection of relationships the start node is also deleted. I am running neo4j community edition 2.3.3 and have run the following queries in order.
match (u:User)-[]->(p:Pie)-[c:CONSISTS_OF*1]->() where id(u) = 6398 and id(p)= 6436 return p,c Which returns Displaying 3 nodes, 2 relationships. and the graph in the image
match (u:User)-[]->(p:Pie)-[c:CONSISTS_OF*1]->() where id(u) = 6398 and id(p)= 6436 FOREACH( q in c | DELETE q) Which results in Deleted 2 relationships, statement executed in 103 ms.
And then what I am finding is instead of the collection of relationships c being deleted, the node p is also deleted…
match (u:User)-[]->(p:Pie)-[c:CONSISTS_OF*1]->() where id(u) = 6398 and id(p)= 6436 return p Which results in (no rows)
I would simply like to delete the collection of relationships. I also feel like this feature is something that makes sense but hasn’t been revisited since late 2013… https://github.com/neo4j/neo4j/issues/1612
EDIT: In an earlier version of the question I had DETACH DELETE instead of DELETE. This was a mistake in the posting of the question. I have since revised it. It should be noted that the reason I think this may be a bug is because both DETACH DELETE and DELETE behave the same in this scenario.
In the MATCH query that you use to check whether the (p:Pie) node exists after deleting the relationships you still include the -[c:CONSISTS_OF*1]-> part of the pattern. That part doesn't match anything, because you deleted those relationships. But then the whole pattern won't match anything either, whether or not the node still exists.
You can use MATCH (p:Pie) WHERE id(p) = 6436 to test that the (p:Pie) node still exists.

How to delete a linkedlist in neo4j?

I have created a linked list structure for a feed scenario. Here i have my feeds persisted in the linked-list in neo4j. This is working fine. However, there might be a need to delete the whole product, so I am trying to come up with a cypher that can delete the product and the related linked list for feeds in one query.
This query returns me correct data
match p = (i:Item {uuid:"d98c299d-239b-40d1-ac2f-01a80ac36db4"})-[:LATEST]-(latestComment), latestComment-[:NEXT*0..]-(olders) return i, latestComment, olders;
based on these lines, I tried writing a delete query and its certain variations using foreach, but nothing seems to be working.
match p = (i:Item {uuid:"d98c299d-239b-40d1-ac2f-01a80ac36db4"})-[:LATEST]-(latestComment), latestComment-[:NEXT*0..]-(olders) delete i, latestComment, olders;
error:
Node record Node[13349,used=false,rel=26286,prop=-1,labels=Inline(0x0:[]),light] still has relationships
a variation with foreach
match (i:Item {uuid:"d98c299d-239b-40d1-ac2f-01a80ac36db4"})-[:LATEST]-(latestComment), latestComment-[:NEXT*0..]-(olders) delete i, foreach (old in olders | delete old)
clearly there is something wrong, but I am not getting enough pointers towards the possible error.
In order to delete a node, you must also delete all relationships touching that node. You queries do not do that.
In your case, since you want to delete the entire path, you might be able to simply do this:
MATCH p =(i:Item { uuid:"d98c299d-239b-40d1-ac2f-01a80ac36db4" })-[latest:LATEST]-(latestComment)-[:NEXT*0..]-(olders)
DELETE p;
However, if any node in the path has relationships that are not also in the path, then the above query need to be modified to include those extra relationships.

How to make WITH Neo4J Cypher 2 query more efficient?

I had a query of this kind, which would basically find a specific node "Statement", find all the nodes connected to it with an :OF relation, find all their connections to one another, as well all the relations of the node "Statement" to other nodes and the node "Statement" itself:
MATCH (s:Statement{uid:"e63cf470-ade4-11e3-bc66-2d7f9b2c7878"}),
c1-[:OF]->s<-[:OF]-c2, c1-[to:TO]->c2
WITH DISTINCT to, c1, c2, s
MATCH c1-[by:BY]->u, c2-[at:AT]->ctx
WHERE to.statement="e63cf470-ade4-11e3-bc66-2d7f9b2c7878"
AND by.statement="e63cf470-ade4-11e3-bc66-2d7f9b2c7878"
AND at.statement="e63cf470-ade4-11e3-bc66-2d7f9b2c7878"
DELETE s,rel,to,by,at;
This worked OK for when there was 3 nodes connected to the node "Statement", but when there's a 100, it crashes the database.
I tried playing around passing different nodes and relationships with a WITH, but it didn't help.
The closest to a solution that I could get was to set up automatic indexing on relationship properties and then execute the deletion with two queries:
MATCH (s:Statement{uid:"e63cf470-ade4-11e3-bc66-2d7f9b2c7878"}),
s-[by:BY]->u, s-[in:IN]->ctx, c-[of:OF]->s DELETE by,in,of,s;
START rel=relationship:relationship_auto_index
(statement="e63cf470-ade4-11e3-bc66-2d7f9b2c7878")
DELETE rel;
2 Questions:
1) I know that the first query took too long because there were too many iterations. How to avoid that?
2) Do you know how to combine the two faster queries above into one so that it works fast and preferably without using the relationship index and START clause?
Thank you!
For this statement
You must not separate the condition on to from the match. Then Cypher will find all matches first and only filter after it is done with that.
MATCH (s:Statement{uid:"e63cf470-ade4-11e3-bc66-2d7f9b2c7878"}),
c1-[:OF]->s<-[:OF]-c2, c1-[to:TO]->c2
WHERE to.statement="e63cf470-ade4-11e3-bc66-2d7f9b2c7878"
WITH DISTINCT to, c1, c2, s
MATCH c1-[by:BY]->u, c2-[at:AT]->ctx
WHERE by.statement="e63cf470-ade4-11e3-bc66-2d7f9b2c7878"
AND at.statement="e63cf470-ade4-11e3-bc66-2d7f9b2c7878"
DELETE s,rel,to,by,at;
Also I'm not sure if this c1-[:OF]->s<-[:OF]-c2, c1-[to:TO]->c2 doesn't span up a cross-product.
Just do this:
MATCH (s:Statement{uid:"e63cf470-ade4-11e3-bc66-2d7f9b2c7878"}),
c1-[:OF]->s<-[:OF]-c2, c1-[to:TO]->c2
WHERE to.statement="e63cf470-ade4-11e3-bc66-2d7f9b2c7878"
RETURN count(*),count(distinct c1), count(distinct c2), count(distinct to)
to see some numbers.
You also don't seem to use (u) and (ctx) in the result? So might be an option to convert that into a condition. (Have to try), then you might even be able to leave of the with (if the cardinality with distinct is not much smaller than without.
....
WHERE c2-[:AT {at.statement:"e63cf470-ade4-11e3-bc66-2d7f9b2c7878"}]->()
AND c1-[:BY {statement:"e63cf470-ade4-11e3-bc66-2d7f9b2c7878"}]->()
DELETE s,rel,to,b
HTH
Would love to get the dataset to try it out.

Resources