36

I am trying to make a database where every time a node doesn't exist it will create a new one and set a relationship between this node and another. If the node exists, both nodes get a relationship.

My problem is that, if I try to connect 2 existing nodes, the 2nd node will be recreated. I tried with MERGE and CREATE UNIQUE, both didn't work.

My example code:

CREATE (test1 name:'1'})
MATCH (n)
WHERE n.name = '1'
MERGE (n)-[:know {r:'123'}]->(test3 {name:'3'})

MATCH (n)
WHERE n.name = '1'
MERGE (n)-[:know {r:'123'}]->(test2 {name:'2'})

Till here it works but with:

MATCH (n)
WHERE n.name = '3'
MERGE (n)-[:know {r:'123'}]->(test2 {name:'2'})

it creates a new node "2" instead of connecting to the existing one.

David Makogon
  • 69,407
  • 21
  • 141
  • 189
Kapotth
  • 393
  • 1
  • 3
  • 8

1 Answers1

60

When using MERGE on full patterns, the behavior is that either the whole pattern matches, or the whole pattern is created. MERGE will not partially use existing patterns — it’s all or nothing. If partial matches are needed, this can be accomplished by splitting a pattern up into multiple MERGE clauses. http://docs.neo4j.org/chunked/stable/query-merge.html

MERGE (n)-[:know {r:'123'}]->(test2 {name:'2'}) will try to match the entire pattern and since it does not exist, it creates it. What you can do is:

MERGE (n {name: '3'}) //Create if a node with name='3' does not exist else match it
MERGE (test2 {name:'2'}) //Create if a node with name='2' does not exist else match it
MERGE (n)-[:know {r:'123'}]->(test2) //Create the relation between these nodes if it does not already exist
Luanne
  • 19,145
  • 1
  • 39
  • 51
  • 3
    you don't have to use 3 merge as 3 Cypher. You can chain 3 merge in 1 cypher (one line) to save overhead time of networking – Haha TTpro Aug 18 '18 at 03:51
  • 2
    @HahaTTpro how to do that? do you mind showing an example? – tim Jul 23 '19 at 22:37
  • I think what he means is that you can write it all in one line/command: MERGE (n {name: '3'}) MERGE (test2 {name:'2'}) MERGE (n)-[:know {r:'123'}]->(test2); – pharaohlxvi Dec 02 '20 at 13:29
  • 2
    the way tcp packets are created this (one line or three) may or may not make any difference and will not ever make a bigger difference than writing readable code so use which-ever you are more comfortable with. – keithpjolley Jan 09 '21 at 15:49
  • 1
    (not to mention will make zero difference when your db is running on your desktop) – keithpjolley Jan 09 '21 at 15:50
  • @HahaTTpro typical "you shouldn't..." response without providing a solution – cryanbhu Mar 17 '21 at 06:57
  • 1
    i believe the "overhead time of networking" only comes into effect if each line is separated with `;`, otherwise Cypher is all processed as 1 transaction. If you break your query lines with `;` you'll see that they each have a status tick when running in Neo4J Browser. – cryanbhu Mar 17 '21 at 06:59
  • It's worth being aware that if you are running this multipletimes asynchronously that you need a constraint - see https://github.com/neo4j/neo4j/issues/3437 – SteveR Sep 09 '21 at 06:04