Arjun
Arjun

Reputation: 907

neo4j - MERGE creates duplicate Node

I have two Person Nodes.

(p:Person {Name: 'Anthony'})
(p:Person {Name: 'Jason'})

The required Relationship is:

(p:Person)-[KNOWS]-(s:Skill) //s is dynamically entered

To Achieve this, I used the Query:

MATCH (p:Person) 
WHERE p.Name='Anthony'
MERGE(p)-[r:KNOWS{Weight:83}]-(x:Skill {Name:"WordPress"})

However, if I try it again with:

MATCH (p:Person) 
WHERE p.Name='Jason' 
MERGE(p)-[r:KNOWS{Weight:80}]-(x:Skill {Name:"WordPress"})

The Node (s:Skill {Name: 'WordPress'}) is created again.

I understand that MERGE will match the entire pattern but how can I ensure that this query only creates the Skill Node if it does not exist?

Upvotes: 10

Views: 4065

Answers (4)

Avanti Patil
Avanti Patil

Reputation: 46

Always have a habit of having constraints (unique/asserts) when dealing with Neo4j nodes and relationship in order to avoid duplication mess because it's even more difficult to clean it. Not sure how much this link will help you but do take a look at constraints offered on official Neo4j site.

Upvotes: 1

Christophe Willemsen
Christophe Willemsen

Reputation: 20175

There is another blog post explaining very well the behaviour of MERGE : http://graphaware.com/neo4j/2014/07/31/cypher-merge-explained.html

On a side node and I repeat this often when doing trainings or helping clients : MERGE doesn't prevent duplicates, ONLY uniqueness constraints does!

Upvotes: 5

InverseFalcon
InverseFalcon

Reputation: 30397

Keep in mind that your MERGE is looking for that entire pattern, including the value you included. When you tried to MERGE with the :KNOWS relationship and a different weight property, it couldn't find such a relationship with such a property, so it created the entire pattern.

The other problem with that query was, as you discovered, a new :Skill node being created when the pattern gets created, even if there was an existing :Skill already in the graph. As you discovered, doing a MERGE on just the skill first is necessary before you MERGE the pattern.

As for dealing with a new property value, that's best done after you MERGE the pattern (excluding the property in the MERGE).

For example:

MATCH (p: Person)
WHERE p.Name='Jason'
MERGE (s:Skill {Name: 'Wordpress'})
MERGE (p)-[r:KNOWS]-(s)
SET r.Weight = 80

Also useful, after a MERGE you can use ON CREATE and ON MATCH respectively to perform additional operations (usually SET operations) depending on whether the MERGE matched an existing pattern, or instead created it.

Upvotes: 11

Arjun
Arjun

Reputation: 907

Thanks to an interesting blog post: Here's a link!

I found out that the solution is:

MATCH (p: Person)
WHERE p.Name='Jason'
MERGE (s:Skill {Name: 'Wordpress'})
CREATE UNIQUE (p)-[r:KNOWS {Weight:80}]-(s)
RETURN (r)

Still interested in any other answer! :)

Upvotes: 2

Related Questions