cancel
Showing results for 
Search instead for 
Did you mean: 

Join the community at Nodes 2022, our free virtual event on November 16 - 17.

How to handle relationships for a part of a graph?

marcelix161
Node Clone

I have the following graph.

Is it possible to remove only one from those reciprocal relationships or to make them point in the same direction?

1 ACCEPTED SOLUTION

Cobra
Ninja
Ninja

Hello @marcelix161

You should have a look at the APOC function apoc.refractor.mergeRelationships() which is able to remove duplicate relationships by merging them:

MATCH (a)-[r:MINST2]-(b)
CALL apoc.refactor.mergeRelationships(collect(r), {
    properties: "overwrite"
})

Regards,
Cobra

View solution in original post

13 REPLIES 13

glilienfield
Ninja
Ninja

Do you care which direction remains, i.e, blue-to-orange nodes or orange-to-blue, or can one be removed randomly?

If you care, indicate the node labels and direction you want to delete.

marcelix161
Node Clone

Hi @glilienfield
Thank you for your hint.
The problem is that I'd need to apply it dynamically while uploading many graphs. 😞

glilienfield
Ninja
Ninja

Well, in general, you would remove a relationship with the following query. You can adapt it to your situation.

match(:Label1)-[r:REL_TYPE]->(:Label2)
delete r

hm, but that will destroy the rest of the graph 😞

glilienfield
Ninja
Ninja

no, no....it is just a pattern...you need to adapt it to your specific needs to restrict it to correct nodes and relationships.

giuseppe_villan
Graph Fellow

@marcelix161

If you want a solution as general as possible to remove reciprocal relationships,
you could do:

match p=(a)-[r1]->(b), (b)-[r2]->(a) 
where id(r1) < id(r2) // to avoid double a, b results
delete r2

but, as said above, it's better to adapt your case, of course if possible,
by adding start and end labels to a and b and changing where id(r1) < id(r2) with a specific property.

Cobra
Ninja
Ninja

Hello @marcelix161

You should have a look at the APOC function apoc.refractor.mergeRelationships() which is able to remove duplicate relationships by merging them:

MATCH (a)-[r:MINST2]-(b)
CALL apoc.refactor.mergeRelationships(collect(r), {
    properties: "overwrite"
})

Regards,
Cobra

Hi @Cobra ,

I find your idea helpful and I've been trying to apply it but to no avail.
I think I am able to write a query without errors but it doesn't do anything as well.

My cypher:

match (g:GId)-[rel:MINST]->(c:CId)
with g,c, collect(rel) as rels
unwind rels as r
call apoc.refactor.mergeRelationships(rels,{properties:"overwrite"})
yield rel
return rel

Do you think you could help me out?

Cobra
Ninja
Ninja
MATCH (g:GId)-[rel:MINST]->(c:CId)
WITH g, c, collect(rel) AS rels
CALL apoc.refactor.mergeRelationships(rels, {properties: "overwrite"})
YIELD rel
RETURN rel

marcelix161
Node Clone

Hi @Cobra ,

Thank you for your input, but it doesn't seem to work as well 😞
I've created a small dataset simulating the case of the matter.

CREATE (n1:Person {name:'Tom'}),
(n3:Company {name:'Company1'}),
(n5:Car {brand:'Ferrari'}),
(n7:City {name:'London'}),

(n1)-[:WORKS_FOR {since:2015}]->(n3),
(n1)<-[:WORKPLACE_OF {since:2018}]-(n3),
(n3)-[:HAS_HQ {since:2004}]->(n7),
(n1)-[:DRIVE {since:2017}]->(n5);

and then run:

match (a1:Person)-[rel:WORKS_FOR]->(c1:Company)
with a1, c1, collect(rel) as rels
call apoc.refactor.mergeRelationships(rels, {properties:"overwrite"})
yield rel
return rel

But this procedure seems not to work for two different relationships. Am I right? Or is my cypher code incorrect?
Thanks!

Cobra
Ninja
Ninja

There were two issues, the MATCH clause (you have only selected one relationship type) and the apoc.refactor.mergeRelationships() function only works if relationships have the same direction so:

First, you have to change the direction of relationships:

MATCH ()-[r:WORKPLACE_OF]->()
CALL apoc.refactor.invert(r)
YIELD input, output
RETURN input, output;

Then you can merge them:

MATCH (p:Person)-[r]->(c:Company)
WITH p, c, collect(r) AS relationships
CALL apoc.refactor.mergeRelationships(relationships, {properties: "overwrite"})
YIELD rel
RETURN rel

Finally, you can rename the relationships if needed:

MATCH (p:Person)-[r]->(c:Company)
CALL apoc.refactor.setType(r, 'NEW-TYPE')
YIELD input, output
RETURN input, output

marcelix161
Node Clone

Hi @Cobra,

ok. Thank you. I wanted to avoid inversion
But, I guess this is not possible.
In such a case do you know how to call procedure on multiple such relationships at once?

match p=(g:GId {start_marker: 1})-[r:MINST2*2]-(leaf)
with collect(r) as rels
unwind rels as rel
call apoc.refactor.invert(rel)

does not work, but if I use return instead of a procedure it seems to work fine.

Cobra
Ninja
Ninja

What is the right direction between Gid and CId?

(g:GId)-[rel:MINST]->(c:CId)

Or

(g:GId)<-[rel:MINST]-(c:CId)