質問

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.

他のヒント

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.

I think where clause wont be required.

match (t0)-[r0:RT]->(t1)-[r1:RT]->(t0)
delete r0

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)
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top