How to handle relationships for a part of a graph?

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?

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.

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

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 :(

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

@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.

Hello @marcelix161 :slight_smile:

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

1 Like

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?

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

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!

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

Hi @Cobra,

ok. Thank you. I wanted to avoid inversion :slight_smile:
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.

What is the right direction between Gid and CId?

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

Or

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