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?
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.
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.
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.
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.
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.
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With