Reputation: 313
I have an XML file with the following pattern: nodes with the ref property have the same value as the id property of other nodes. This is a visual example in Neo4j:
The yellow one has the ref property (ref=2) value as TWO (id=2).
My goal is to create a graph, deleting each node with the ref value that is equal to other id nodes, but also preserving the relationship isFatherOf that has to point to the other node, in this case, TWO.
Here is the outcome of the procedure:
I'm able to delete all the ref nodes with the following procedure,
match (n1:Node)
with collect(distinct n1.id) as ids
collection called 'ids'
match (n2:Node)
where n2.ref in ids
detach delete n2
but I do not know how to preserve the relationships. Is there a way to do that?
Upvotes: 1
Views: 531
Reputation: 16373
I have reproduced your scenario using this sample data model:
create (one:Node {id : 1, name : 'ONE'}),
(two:Node {id : 2, name : 'TWO'}),
(ref:Node {ref:2}),
(one)-[:isFatherOf]->(ref)
The following Cypher query should do the work:
// get all 'n1' nodes point to an node with 'ref' property
match (n1:Node)-[r:isFatherOf]->(refNode:Node)
where exists(refNode.ref)
// match 'n2' nodes that have an ID equal to 'n2.ref'
match (n2:Node {id : refNode.ref})
// create a new relationship between 'n1' and 'n2'
create (n1)-[:isFatherOf]->(n2)
// remove node with 'ref' properties and all relationships
detach delete refNode
For the sample data set the output will be:
If you need to preserve the original relationship instead of creating a brand new one, then you will need to use the APOC Procedure apoc.refactor.to
. This procedure redirects the relationship to use new end-node.
match (n1:Node)-[r:isFatherOf]->(refNode:Node)
where exists(refNode.ref)
match (n2:Node {id : refNode.ref})
// redirecting 'r' to use 'n2' as end node
call apoc.refactor.to(r, n2) yield output
delete refNode
The output will be the same.
Upvotes: 1