Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

neo4j - MERGE creates duplicate Node

Tags:

neo4j

cypher

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?

like image 489
Arjun Avatar asked Dec 31 '16 11:12

Arjun


People also ask

How does merge work in Neo4j?

What is MERGE, and how does it work? The MERGE clause ensures that a pattern exists in the graph. Either the entire pattern already exists, or the entire pattern needs to be created. In this way, it's helpful to think of MERGE as attempting a MATCH on the pattern, and if no match is found, a CREATE of the pattern.

How do I merge two nodes in Neo4j?

You can merge a node in the database based on the label using the MERGE clause. If you try to merge a node based on the label, then Neo4j verifies whether there exists any node with the given label. If not, the current node will be created.

What is unwind in Neo4j?

With UNWIND , you can transform any list back into individual rows. These lists can be parameters that were passed in, previously collect -ed result or other list expressions. One common usage of unwind is to create distinct lists. Another is to create data from parameter lists that are provided to the query.

What is optional match in Neo4j?

An OPTIONAL MATCH matches patterns against your graph database, just like a MATCH does. The difference is that if no matches are found, OPTIONAL MATCH will use a null for missing parts of the pattern. OPTIONAL MATCH could be considered the Cypher equivalent of the outer join in SQL.


2 Answers

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.

like image 113
InverseFalcon Avatar answered Sep 25 '22 12:09

InverseFalcon


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!

like image 21
Christophe Willemsen Avatar answered Sep 22 '22 12:09

Christophe Willemsen