25

When I run this query:

START n1=node(7727), n2=node(7730)
MATCH n1-[r:SKILL]->n2 RETURN r

it gives me a list of duplicate relationships that I have between the two nodes. what do I add to the cypher query to iterate over the relationship to keep one relationship and delete the rest?

Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
priyolahiri
  • 668
  • 1
  • 5
  • 10

4 Answers4

42

To do this for two known nodes:

start n=node(1), m=node(2) match (n)-[r]->(m) 
with n,m,type(r) as t, tail(collect(r)) as coll 
foreach(x in coll | delete x)

To do this globally for all relationships (be warned this operation might be very expensive depending on the size of your graph):

start r=relationship(*) 
match (s)-[r]->(e)
with s,e,type(r) as typ, tail(collect(r)) as coll 
foreach(x in coll | delete x)
radicand
  • 6,068
  • 3
  • 27
  • 22
Stefan Armbruster
  • 39,465
  • 6
  • 87
  • 97
  • 2
    In recent versions of neo4j, I believe the `START` clause is unnecessary, right? It seems to work the same without it. – Ken Williams Dec 18 '14 at 00:25
  • 3
    I didn't understand how this worked until I realised `tail` returns all but the first element. thanks! – fiat Jul 28 '16 at 05:30
  • I was wondering where you found the "relationship" function you use? I don't see it in the documentation anywhere, only "relationships". Is it an older function? – pooshla Jan 23 '19 at 19:10
  • 2
    this has been removed long time ago. These days you would just omit the first line and begin the statement with `match`. – Stefan Armbruster Jan 26 '19 at 09:19
7

With Neo4J 4.x and to globally remove duplicate relationships, you'll want to use the following instead. The syntax has changed slightly and the start prefix mentioned in the other reply no longer works.

match ()-[r]->() 
match (s)-[r]->(e) 
with s,e,type(r) as typ, tail(collect(r)) as coll 
foreach(x in coll | delete x)
chris_g
  • 71
  • 1
  • 2
  • 1
    Note, why the first line? (I think it is not needed) match ()-[r]->() – plastic Jan 28 '21 at 16:41
  • why wouldn't `match ()-[r:RELTYPE]-() with type(r) as typ, tail(collect(r)) as coll foreach(x in coll | delete x);` work instead? Why does it delete all the relationships with that type? – Ooker Dec 07 '21 at 05:55
3

If you have trust issues about random queries that deletes data from the DB you can do what I did.

First you might want to check if the selected relationships are really duplicates. This query will set a property willBeDeleted to true, so you can check if you really want to delete those.

match (a)-[r]->(b) 
with a,b,type(r) as typ, tail(collect(r)) as coll 
foreach(x in coll | set x.willBeDeleted=true)

Now you can check which relationships will be deleted actually.

match(a)-[r]-(b)
where r.willBeDeleted=true
return a, b, r

If you think the right relationships will be deleted, then you can execute this query to delete the duplicates.

match (a)-[r]->(b) 
with a,b,type(r) as typ, tail(collect(r)) as coll 
foreach(x in coll | delete x)
Andras Kloczl
  • 8,415
  • 2
  • 21
  • 23
0

Here's a great way to find all your duplicate relationships and get some visibility into where they are happening.

MATCH p=(n)-[r1]->(g)<-[r2]-(n)
WHERE type(r1) = type(r2) AND r1 <> r2
RETURN type(r1) as relType, labels(n), labels(g), count(p)
ogoldberg
  • 781
  • 7
  • 8