neo4jcypher

How to specify more than two relationships to the same node in a `MERGE`


I have this situation

CREATE (a:X { id: 1 })
CREATE (b:Y { id: 2 })
CREATE (c:Z { id: 3 })
CREATE (:Z { id: 4 })
CREATE (a)-[:HAS]->(d:W { id: 5 })<-[:HAS]-(b)
CREATE (c)-[:HAS]->(d)

Initial situation

And I want to run this query

MATCH (a:X { id: 1 })
MATCH (b:Y { id: 2 })
MATCH (c:Z { id: 4 }) // The one with no relationships yet
MERGE (a)-[:HAS]->(d:W)<-[:HAS]-(b), (d)<-[:HAS]-(c)
ON CREATE SET d.id = 6

The problem is that I'm not allowed to put more than one path in a single MERGE, how can I do this?

This is the result I want to achieve

Expected result

Notice that I can't just do this

MATCH (a:X { id: 1 })
MATCH (b:Y { id: 2 })
MATCH (c:Z { id: 4 })
MERGE (a)-[:HAS]->(d:W)<-[:HAS]-(b) // This path already exists, but it uses the other `Z`
ON CREATE SET d.id = 6
MERGE (d)<-[:HAS]-(c) // Separate merge

Because the result would be

What I don't want


Solution

  • In order to create three relationships connecting three existing nodes to a new node with label W — but only if those nodes are not already so connected — you can do it using CREATE:

    MATCH (a:X { id: 1 }), (b:Y { id: 2 }), (c:Z { id: 4 })
      WHERE NOT EXISTS { (a)-[:HAS]->(d:W)<-[:HAS]-(b), (d)<-[:HAS]-(c) }
    CREATE (a)-[:HAS]->(d:W)<-[:HAS]-(b), (d)<-[:HAS]-(c)
    

    If the pattern in NOT EXISTS already exists, then MATCH produces no rows for CREATE to execute over i.e. nothing is created.