I have recently started using Neo4j (version 3.4.1) and still learning the nuances. I have the following the node relationship in my application.
What I am trying to achieve is the following.
I can delete nodes C1 or C2. I am able to delete their corresponding relationships as well (i.e HAS_X or HAS_Y).
However, when I delete both C1 and C2, node L1 and its other related nodes (M1, M2 and M3) become orphans. Hence, what I want is that whenever I am deleting C1 or C2, if it is the only node that has HAS_Y relationship with node L1, then in that case node L1 and its related nodes (M1, M2 and M3) should also be deleted. If it is not the only node that has HAS_Y relationship with L1, in that case we just delete that specific node (i.e C1/C2). Node L1 and rest of the nodes are left unotuched.
Nodes U1 and U2 remain unaffected in both the scenarios.
I am not sure how I can achieve this using a single cypher query.
Note : I was able to achieve my goal by running 2 separate queries (1 for deleting node C1/C2 and another one for deleting orphan node L1). However, it isn't the most performant as I have to make 2 roundtrips to db.
Is anyone able to give me some inputs on how I can achieve this task? I am looking for a cyper query solution (I am avoiding APOC procedures atm as I hear it requires some modification to neo4j db config)
Regards,
V
You should be able to do this with just Cypher:
...// above is your match to 'c', the node to delete
OPTIONAL MATCH (c)-[:HAS_Y]->(l)
DETACH DELETE c
WITH DISTINCT l
WHERE size(()-[:HAS_Y]->(l)) = 0
OPTIONAL MATCH (l)-[:HAS_Z*0..1]->(toDelete)
DETACH DELETE toDelete
We first match to l, then we delete c. At this point, we only have to take action for any l nodes that no longer have any incoming :HAS_Y relationships. We filter just for these, and then use an optional match with a 0..1 variable relationship to capture both the l nodes and any children they have down :HAS_Z relationships, then delete all of those nodes (both l and all of its possible children will be addressed via toDelete).
Related
How can I create full node tree from existing node tree, Actually i have 1 node and i need to find all relation and nodes that has my existing top node. I need to create full node tree to another node.
Copy All Node Tree from A with Relation and create Duplicate same node and relation for B Node
Okay, this is a tricky one.
As others have mentioned apoc.refactor.cloneNodesWithRelationships() can help, but this will also result in relationships between cloned nodes and the originals, not just the clones, as this proc wasn't written with this kind of use case in mind.
So this requires us to do some Cypher acrobatics to find the relationships from the cloned nodes that don't go to the cloned nodes so we can delete them.
However at the same time we also have to identify the old root node so we can refactor relationships to the new root (this requires separate processing for incoming and outgoing relationships).
Here's a query that should do the trick, making assumptions about the nodes since you didn't provide any details about your graph:
MATCH (a:Root{name:'A'})
WITH a, id(a) as aId
CALL apoc.path.subgraphNodes(a, {}) YIELD node
WITH aId, collect(node) as nodes
CALL apoc.refactor.cloneNodesWithRelationships(nodes) YIELD input, output
WITH aId, collect({input:input, output:output}) as createdData, collect(output) as createdNodes
WITH createdNodes, [item in createdData WHERE item.input = aId | item.output][0] as aClone // clone of root A node
UNWIND createdNodes as created
OPTIONAL MATCH (created)-[r]-(other)
WHERE NOT other in createdNodes
DELETE r // get rid of relationships that aren't between cloned nodes
// now to refactor relationships from aClone to the new B root node
WITH DISTINCT aClone
MATCH (b:Root{name:'B'})
WITH aClone, b
MATCH (aClone)-[r]->()
CALL apoc.refactor.from(r, b) YIELD output
WITH DISTINCT b, aClone
MATCH (aClone)<-[r]-()
CALL apoc.refactor.to(r, b) YIELD output
WITH DISTINCT aClone
DETACH DELETE aClone
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.
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
I want to delete all the relationships and nodes when deleting a particular node
For example
I have a structure like
A->B->C->D->D1->E1
->D2
->D3
What I want is when I delete node B, all the relations and nodes which are directly or indirectly connected to this node B gets deleted
like if I delete B then C, D D1, D2, D3, E1 should get deleted as well as their relations.
Is there a way to do that?
I have a graph wherein a state node has a lot of store nodes and each store nodes have a lot of items nodes and each item nodes have a lot of price nodes.
Now if I delete State node, all the store which are connected to it should get deleted, and all the items which are connected to these stores should get deleted and then the price nodes which are connected to these items nodes should bet deleted
The following Cypher query will remove an entire subgraph rooted at a specific node.
I pretend that you find the root of the subgraph by testing that its xxx property has the value 'yyy'.
MATCH (root {xxx:'yyy'})-[r1*]->(x)
OPTIONAL MATCH ()-[r2]->(root)
FOREACH(r IN r1 | DELETE r)
DELETE r2, root, x;
using Neo4j - Graph Database Kernel 2.0.0-M02 and the new merge function,
I was trying to merge nodes into a new one (merge does not really merges but binds to the returning identifier according to the documentation) and delete old nodes. I only care at the moment about properties to be transferred to the new node and not relationships.
What I have at the moment is the cypher below
merge (n:User {form_id:123}) //I get the nodes with form_id=123 and label User
with n match p=n //subject to change to have the in a collection
create (x) //create a new node
foreach(n in nodes(p): set x=n) //properties of n copied over to x
return n,x
Problems
1. When foreach runs it creates a new x for every n
2. Moving properties from n to x is replacing all properties each time with the new n
so if the 1st n node from merge has 2 properties a,b and the second c,d in the and after the set x=n all new nodes end up with c,d properties. I know is stated in the documentation so my question is:
Is there a way to merge all properties of N number of nodes (and maybe relationships as well) in a new node with cypher only?
I don't think the Cypher language currently has a syntax that non-destructively copies any and all properties from one node into another.
However, I'll present the solution to a simple situation that may be similar to yours. Let's say that some User nodes have the properties a & b, and some others have c & d. For example:
CREATE (:User { id:1,a: 1,b: 2 }),(:User { id:1,c: 3,d: 4 }),
(:User { id:2,a:10,b:20 }),(:User { id:2,c:30,d:40 });
This is how we would "merge" all User nodes with the same id into a single node:
MATCH (x:User), (y:User)
WHERE x.id=y.id AND has(x.a) AND has(y.c)
SET x.c = y.c, x.d = y.d
DELETE y
RETURN x
You can try this out in the neo4j sandbox at: http://console.neo4j.org/
With Neo4j-3.x it is also possible to merge two nodes into one using a specific apoc procedure.
First you need to download the apoc procedures jar file in your into your $NEO4J_HOME/plugins folder and start the Neo4j server.
Then you can call apoc.refactor.mergeNodes this way:
MATCH (x:User), (y:User)
WHERE x.id=y.id
call apoc.refactor.mergeNodes([x,y]) YIELD node
RETURN node
As I can see it, the resulting node would have all the properties of both x and y, choosing the values of y if both are set.