Reputation: 247
This is similar to Merge existing records in neo4j, remove duplicates, keep relationships, except that the nodes I want to merge have 0-2 relationships I want to keep.
Take the graph generated by:
create (:Person {name:"Bob"})-[:RELATED_TO]->(:Person {name:"Jane"})-[:FRIENDS_WITH]->(:Person {name:"Tim"})<-[:FRIENDS_WITH]-(:Person {name:"Jane"}),
(:Person {name:"Sally"})-[:RELATED_TO]->(:Person {name:"Jane"})
I want to merge the duplicate Jane nodes, preserving the RELATED_TO and FRIENDS_WITH relationships, removing the duplicates.
From the other question I can get as far as:
match (p:Person {name:"Jane"})
with p.name as name, collect(p) as ps, count(*) as pcount
where pcount > 1
with head(ps) as first, tail(ps) as rest
unwind rest as to_delete
return to_delete
But I can't seem to get the matches and/or optional matches correct for merging. I tried chaining optional matches and doing the merge in one statement and neo4j gives me a Statement.ExecutionFailure with no additional message. I tried breaking out the merges into each match and ended up with "other node is null". Thoughts?
Upvotes: 1
Views: 834
Reputation: 20175
The following query is working. On a side note, for this kind of refactoring I would love the day when it would be possible to set a relationship type with a dynamic variable :
MATCH (n:Person { name:"Jane" })
WITH collect(n) AS janes
WITH head(janes) AS superJane, tail(janes) AS badJanes
UNWIND badJanes AS badGirl
OPTIONAL MATCH (badGirl)-[r:FRIENDS_WITH]->(other)
OPTIONAL MATCH (badGirl)<-[r2:RELATED_TO]-(other2)
DELETE r, r2, badGirl
WITH superJane, collect(other) AS friends, collect(other2) AS related
FOREACH (x IN friends | MERGE (superJane)-[:FRIENDS_WITH]->(x))
FOREACH (x IN related | MERGE (x)-[:RELATED_TO]->(superJane))
Result :
Upvotes: 4