Move/copy all relationships to different node
Asked Answered
E

2

6

Is there any way to copy or move a relationship from one node to another?

I have a situation similar to that here:

neo4j merge 2 or multiple duplicate nodes

and here:

Copy relationships of different type using Cypher

Say I have this pattern in the graph

(a)-[r:FOO]->(b)
(a)<-[r2:BAR]-(c)

I then have another node, (d), which may or may not be a duplicate of (a). My thinking is that it does not matter whether the nodes are duplicate or not from a functionality point of view. I want to be able to move or copy the relationships r:FOO and r2:BAR so that the graph now includes

(d)-[r:FOO]->(b)
(d)<-[r2:BAR]-(c)

If I was then doing this to merge nodes when I have duplicates I would like to be able to move the relationships as opposed to copy and then (perhaps optionally) delete (a). Note that there is more than one relationship type and I do not know for sure what the types will be. I realise I can do this in stages but thought it would be great if there was an efficient way to do it in one cypher query. My current strategy is something like (not exact syntax but just to give an idea)

// get all outgoing relationships
MATCH (a:Label1 { title : 'blah' })-[r]->(o)
RETURN r
// returns FOO and BAR

// for each relationship type, create one from (d) and copy the properties over
MATCH (a:Label1 { title : 'blah' })-[r:FOO]->(o), (d:Label1 { title : 'blah blah' })
CREATE (d)-[r2:FOO]->(o)
SET r2 = r
...etc...

// now do the same for incoming relationships
MATCH (a:Label1 { title : 'blah' })<-[r]-(o)
RETURN r
// returns FOO and BAR
// for each relationship type, create one from (d) and copy the properties over
MATCH (a:Label1 { title : 'blah' })<-[r:FOO]-(o), (d:Label1 { title : 'blah blah' })
CREATE (d)<-[r2:FOO]-(o)
SET r2 = r
...etc...

// finally delete node and relationships (if required)
MATCH (a:Label1 { title : 'blah' })-[r]-(o)
DELETE r, a

However this relies on a number of queries and hence transactions. It would be much preferable (in my simpleton view) to be able to achieve this in one query. However, I do not believe anything like this exists in cypher. Am I wrong?

Any ideas? Let me know if this is not clear and I shall try to elaborate and explain further.

For info, I am using Neo4j 2.1.6 community edition (with neo4jclient from a .NET application).

Just realised that I would also have to repeat my process to account for the direction of the relationship unless I am mistaken? i.e. get all outgoing relationships from (a), recreate them as outgoing from (d), and then do the same for all incoming relationships. Cypher above has been edited accordingly.

UPDATE: I am guessing this is a pipe dream and not at all possible. Can anyone confirm this? It would be good to have a definitive answer even if it is "No!". If so I would consider asking the Neo4j guys if this functionality is even feasible and worth considering.

UPDATE 2: From the lack of ideas I am guessing this can't be done. I certainly have got no further in my research or experimentation. Looks like a feature request is the way to go. I can't be the only person who would find this functionality exceptionally useful.

Erving answered 16/1, 2015 at 13:9 Comment(2)
This feature would be nice. I (think) I may have duplicated this at #32629283Cotterell
For anyone who stumbles upon this, even at version 3.4.5 neo4j does not support the likes of (d)-[r2:type(r)]-(o) -- multiple transactions and dynamically building query based on the first read is the way to goPail
S
0

I think you can just chain these together:

// get all relationships
MATCH
  (a:Label1 { title : 'blah' })-[r]-(o),
  (d:Label1 { title : 'blah blah' })
CREATE (d)-[r2:type(r)]-(o)
DELETE r, a

The only thing I'm not entirely sure about is the ability to use the type() function where it's being used there. I'll try it out now

Sideling answered 16/1, 2015 at 13:20 Comment(7)
Thanks. Be interested to see. I had a go with type(r) but failed - could have been the way I was using it. I like the idea of chaining if it could work.Erving
Yeah, I had the same problem. I don't think that this is possible. There might be a way to use SET, but I'm not seeing it at the moment. You might also look into the WITH clause to reduce the number of statementsSideling
Yep, I have thought of using WITH but unless I am missing something I can only see it saving the final 'clean up' step? Or do you mean WITH a, d repetitively to do everything in one statement?Erving
Plus I think SET only allows you to copy properties as in my question, rather than relationship type?Erving
@BrianUnderwood @Erving Did you both found a solution to make type(r) work?Lundquist
Nope, I didn't, sorry ;(Sideling
@Lundquist Me neither. And apologies for the (very) delayed response.Erving
U
0

I've found this apoc.refactor.to and apoc.refactor.from procedures to do this: https://neo4j.com/labs/apoc/4.1/overview/apoc.refactor/apoc.refactor.to/

Uranic answered 7/1, 2024 at 10:16 Comment(1)
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From ReviewUriah

© 2022 - 2025 — McMap. All rights reserved.