Replace relationship Or switch relationship

cypher
relationship

(Kunal Goyal) #1

Hello Everyone,

I need some help in a scenario related to relationship.
For E.g. currently i am having a relationship between two nodes A and B like below.
A-[rel]->B

now it may be possible that in future it get changed . for all properties and data for relationhsip rel need to switch a node C
now relationship is
A-[rel]->C

how i can do that ?
rel can not be duplicate . if 2nd scenario comes then scenario 1 should be removed.


(Ameyasoft) #2

Hi,

I would like to follow the versioning approach for keeping the data for historical purposes. Here is my approach for your scenario.

Here I add a 'active' property to the relationship and set that to 'yes':
with
CREATE (h:hospital {name:"xyz"})
CREATE (n:owner {name:"abc"})
CREATE (h)-[:OWNER {active:"yes"}]->(n)
RETURN h,n;
hosp1a

Create a new owner node and connect it to hospital node setting the OWNER property to 'yes' . Prior to this set the OWNER property to 'no'.

Cypher query:

MATCH (c:hospital)-[r:OWNER]->(d:owner)
WHERE c.name="xyz" AND d.name = "abc"
SET r.active = "no"
CREATE (f:owner {name:"cde"})
CREATE (c)-[:OWNER {active:"yes"}]->(f)
RETURN c, d, f;
hosp2a

After this you can delete the old owner node with appropriate queries.
Remember to query on [:OWNER {active:"yes"}] relationship.

-Kamal


(Andrew Bowman) #3

There is an APOC Procedure for this, refactoring a relationship which will do the whole create-new-then-delete-old relationship process for you.

...
// assume a, b, c, and rel are already in scope
CALL apoc.refactor.to(rel, c) YIELD input, output, error
RETURN input, output, error

(Kunal Goyal) #4

Thanks @ameyasoft and @andrew.bowman

i am refactoring relationship with data using batch import.
will it work in this case ??


(Ameyasoft) #5

Hi Andrew,

Looks like refactoring relationship works strictly for only two nodes: (a)-[:]->(b).
When applied this to (a)-[:]->(b)-[:]-(d).... scenario it deleted all the nodes past (b).

Before:
refact1a

After:
refact2a

Recently I learnt this hard way (losing data). No mention of this in APOC user guide.
-Kamal


(Andrew Bowman) #6

@ameyasoft I'm not quite following what you attempted here, and to my knowledge nodes would not be deleted by a relationship refactoring call.

Please provide more information, preferably cypher to create the smallest example graph needed and the queries used to reproduce this outcome.


(Ameyasoft) #7

Hi,

Redirecting [:ZIPCODE] relationship to (d:Zip2 {id:2135}) from (d:Zip2 {id:1234})

Query 1:
CREATE (c:County {name:"xyz"})-[r:ZIPCODE]->(h:Zip {id:1234})-[:PLACE]->(e:Place {name:"abc"})-[:TYPE]->(k:Type {name:"cv"})
CREATE (d:Zip2 {id:2135})
RETURN *;
relrefactor3a

MATCH (c:County {name:"xyz"})-[r:ZIPCODE]->(h:Zip {id:1234})-[:PLACE]->(e:Place {name:"abc"})-[:TYPE]->(k:Type {name:"cv"})
MATCH (d:Zip {id:2135}) WITH d, c, r
CALL apoc.refactor.to(r, d) YIELD input, output, error
RETURN *;
relrefactor4a

Looking at this I thought I lost other nodes. After spending some time I tried MATCH(n) RETURN n and this is what I found:
relrefactor5a

This broke one path into two paths. Luckily it was a test database. To connect these two broken paths used apoc.refactor.mergeNodes([node1,node2])

Query 2:
MATCH (d:Zip {id:2135}), (a:Zip {id:1234})
CALL apoc.refactor.mergeNodes([d,a], {properties:"discard"})
YIELD node RETURN node;
relrefactor6a

Above result could easily be obtained with Query 1 and Qurery 2 without redirecting relationship. This shows that refactoring relationship works strictly for only two nodes: (a)-[:]->;(b).

These are my findings.

-Kamal


(Andrew Bowman) #8

Hi Kamal,

This actually looks like correct behavior.

Your original relationship was from the :Country node to the :Zip node with id 1234.

Your call redirected the relationship (deleted the old and created a new relationship) from the :Country node to the :Zip2 node with id 2135. The relationships previously in place (from the :Zip with id 1234 to the :Place node, and the relationship from the :Place node to the :Type node) were not changed in any way, nor were any nodes deleted.

To make sure it's clear, the refactor call is only used to redirect a single relationship from (or to) one node to another, it does not refactor an entire path.

I'm not entirely clear on what outcome were you were expecting to see and how you thought the refactor call was meant to work, but if you open up a separate question with what kind of thing you are attempting to do I may be able to help you with such a query.