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