1

I imported a thesaurus with duplicate "Related Term" relationships so when A and B are related, my graph contains (A)-[:RT]->(B) as well as (B)-[:RT]->(A)

To clean this up, because Neo4j allows me to traverse the graph in both directions, I did

match (t0)-[r0:RT]->(t1)-[r1:RT]->(t2)
where t0=t2 AND id(r0) > id(r1)
delete r0

Is this the fastest way ? Answer : No, because it can be simplified.

Edited into

match (t0)-[r0:RT]->(t1)-[r1:RT]->(t0)
where id(r0)>id(r1)
delete r0
Ken Y-N
  • 14,644
  • 21
  • 71
  • 114
Graphileon
  • 5,275
  • 3
  • 17
  • 31

4 Answers4

2

In Cypher the relationships are unique in each path so unless you break up the query into two separate matches, r1 and r2 will never bind the same relationship.

MATCH (t0)-[r:RT]->(t1)-[:RT]->(t0)
DELETE r

Besides, the relationships declared in your pattern have different direction with regards to (t0), so they can't bind the same relationship for that reason also. You can see this if you break the query up.

MATCH (t0)-[r1:RT]->(t1), (t0)<-[r2:RT]-(t1)

Addendum
As you pointed out in a comment, a pattern like this ends up deleting both relationships after all. This is incidental–each individual match will behave as above and only one relationship is deleted. The reason the query as a whole deletes both relationships is that the pattern is symmetric, i.e. a node will satisfy the pattern in the place designated t0 if and only if it also satisfies the pattern in the place designated t1, or (semi-formally)

(t0)-[:RT]->(t1)-[:RT]->(t0) iff (t1)-[:RT]->(t0)-[:RT]->(t1)

Perhaps I should have said that r1 and r2 can never bind the same relationship at the same time, or in the same match or path. The solution is to break the symmetry. I imagined a local query with a discriminating property

(t0 {name:"t0"})-[r:RT]->(t1)-[:RT]->(t0) 
DELETE r

but for a global query, if you want to do it all at once, comparing id on t0 and t1 is great. Which is exactly the answer you had arrived at already.

jjaderberg
  • 9,844
  • 34
  • 34
  • If what you say is correct, then I don't understand the following: create nodes / relations as follows: CREATE (n1) CREATE (n2) CREATE (n1)-[:XYZ]->(n2) CREATE (n2)-[:XYZ]->(n1) then MATCH (t0)-[r:XYZ]->(t1)-[:XYZ]->(t0) DELETE r deletes both [:XYZ] relations, not just one of them. – Graphileon Feb 28 '14 at 01:08
  • I was thinking your actual query would have properties to identify `t0` or `t1`. You are right, if you run the query with 'anonymous' nodes, each node that is bound as `t0` will later also be bound as `t1`. For each match only one relationship is deleted, but since the same path is matched in reverse the other relationship is deleted too. In that case a comparison on ID will make the nodes (or rels) non-anonymous, the 'mirror pattern' will be excluded and only one relationship deleted. I'll update my answer when I have a minute. – jjaderberg Feb 28 '14 at 09:23
1

I use something like this:

match (s:Node)-[r]-(n:Node) 
with s,n,type(r) as t, tail(collect(r)) as coll 
foreach(x in coll | delete x)

it will remove duplicate and reciprocal relationships regardless of the direction of the edges; However, if you want to specify direction, you can also try:

match (s:Node)-[r]->(n:Node) 
with s,n,type(r) as t, tail(collect(r)) as coll 
foreach(x in coll | delete x)

or the other way around. Hope this helps.

Dee Lu
  • 11
  • 1
  • To reviewers: as indicated by Dee Lu himself, this is same as what @Michael Hunger has already answered. hence, this needs to be closed. – phoenix Jan 11 '16 at 10:26
  • @Sri.U I disagree. This answer contains more information than the other. – CubeJockey Jan 11 '16 at 14:59
0

I think where clause wont be required.

match (t0)-[r0:RT]->(t1)-[r1:RT]->(t0)
delete r0
Sumeet Sharma
  • 2,573
  • 1
  • 12
  • 24
  • your suggestion would delete both relationships ;) but referring to the t0 again would simplify the query anyway and thus will it be faster – Graphileon Feb 26 '14 at 17:38
  • It won't delete both as direction of bothrelations are different . So in above query rel r0 frm t0 to t1 will be deleted – Sumeet Sharma Feb 26 '14 at 19:52
  • If what you say is correct, then I don't understand the following: create nodes / relations as follows: CREATE (n1) CREATE (n2) CREATE (n1)-[:XYZ]->(n2) CREATE (n2)-[:XYZ]->(n1) then MATCH (t0)-[r0:XYZ]->(t1)-[r1:XYZ]->(t0) DELETE r0 deletes both [:XYZ] relations, not just one of them. – Graphileon Feb 28 '14 at 01:00
0

I usually use something like this:

match (t0)-[r:RT]-(t1)
with t0,t1, collect(r) as rels
forach (r in tail(rels) | delete r)
Michael Hunger
  • 41,339
  • 3
  • 57
  • 80