CREATE UNIQUE

The CREATE UNIQUE clause was removed in Cypher® 3.2. Using the CREATE UNIQUE clause will cause the query to fall back to using Cypher 3.1. Use MERGE instead of CREATE UNIQUE; refer to the Introduction for an example of how to achieve the same level of node and relationship uniqueness.

Introduction

CREATE UNIQUE is in the middle of MATCH and CREATE — it will match what it can, and create what is missing.

We show in the following example how to express using MERGE the same level of uniqueness guaranteed by CREATE UNIQUE for nodes and relationships.

Assume the original set of queries is given by:

MERGE (p:Person {name: 'Joe'})
RETURN p

MATCH (a:Person {name: 'Joe'})
CREATE UNIQUE (a)-[r:LIKES]->(b:Person {name: 'Jill'})-[r1:EATS]->(f:Food {name: 'Margarita Pizza'})
RETURN a

MATCH (a:Person {name: 'Joe'})
CREATE UNIQUE (a)-[r:LIKES]->(b:Person {name: 'Jill'})-[r1:EATS]->(f:Food {name: 'Banana'})
RETURN a

This will create two :Person nodes, a :LIKES relationship between them, and two :EATS relationships from one of the :Person nodes to two :Food nodes. No node or relationship is duplicated.

The following set of queries — using MERGE — will achieve the same result:

MERGE (p:Person {name: 'Joe'})
RETURN p

MATCH (a:Person {name: 'Joe'})
MERGE (b:Person {name: 'Jill'})
MERGE (a)-[r:LIKES]->(b)
MERGE (b)-[r1:EATS]->(f:Food {name: 'Margarita Pizza'})
RETURN a

MATCH (a:Person {name: 'Joe'})
MERGE (b:Person {name: 'Jill'})
MERGE (a)-[r:LIKES]->(b)
MERGE (b)-[r1:EATS]->(f:Food {name: 'Banana'})
RETURN a

We note that all these queries can also be combined into a single, larger query.

The CREATE UNIQUE examples below use the following graph:

  N0 [
    label = "name = \'A\'\l"
  ]
  N0 -> N2 [
    color = "#2e3436"
    fontcolor = "#2e3436"
    label = "KNOWS\n"
  ]
  N1 [
    label = "name = \'B\'\l"
  ]
  N2 [
    label = "name = \'C\'\l"
  ]
  N3 [
    label = "name = \'root\'\l"
  ]
  N3 -> N2 [
    color = "#4e9a06"
    fontcolor = "#4e9a06"
    label = "X\n"
  ]
  N3 -> N1 [
    color = "#4e9a06"
    fontcolor = "#4e9a06"
    label = "X\n"
  ]
  N3 -> N0 [
    color = "#4e9a06"
    fontcolor = "#4e9a06"
    label = "X\n"
  ]

Create unique nodes

Create node if missing

If the pattern described needs a node, and it can’t be matched, a new node will be created.

Query
MATCH (root { name: 'root' })
CREATE UNIQUE (root)-[:LOVES]-(someone)
RETURN someone

The root node doesn’t have any LOVES relationships, and so a node is created, and also a relationship to that node.

Result
+------------+
| someone    |
+------------+
| Node[20]{} |
+------------+
1 row
Nodes created: 1
Relationships created: 1

Create nodes with values

The pattern described can also contain values on the node. These are given using the following syntax: prop: <expression>.

Query
MATCH (root { name: 'root' })
CREATE UNIQUE (root)-[:X]-(leaf { name: 'D' })
RETURN leaf

No node connected with the root node has the name D, and so a new node is created to match the pattern.

Result
+--------------------+
| leaf               |
+--------------------+
| Node[20]{name:"D"} |
+--------------------+
1 row
Nodes created: 1
Relationships created: 1
Properties set: 1

Create labeled node if missing

If the pattern described needs a labeled node and there is none with the given labels, Cypher will create a new one.

Query
MATCH (a { name: 'A' })
CREATE UNIQUE (a)-[:KNOWS]-(c:blue)
RETURN c

The 'A' node is connected in a KNOWS relationship to the 'c' node, but since 'C' doesn’t have the blue label, a new node labeled as blue is created along with a KNOWS relationship from 'A' to it.

Result
+------------+
| c          |
+------------+
| Node[20]{} |
+------------+
1 row
Nodes created: 1
Relationships created: 1
Labels added: 1

Create unique relationships

Create relationship if it is missing

CREATE UNIQUE is used to describe the pattern that should be found or created.

Query
MATCH (lft { name: 'A' }),(rgt)
WHERE rgt.name IN ['B', 'C']
CREATE UNIQUE (lft)-[r:KNOWS]->(rgt)
RETURN r

The left node is matched against the two right nodes. One relationship already exists and can be matched, and the other relationship is created before it is returned.

Result
+--------------+
| r            |
+--------------+
| :KNOWS[20]{} |
| :KNOWS[3]{}  |
+--------------+
2 rows
Relationships created: 1

Create relationship with values

Relationships to be created can also be matched on values.

Query
MATCH (root { name: 'root' })
CREATE UNIQUE (root)-[r:X { since: 'forever' }]-()
RETURN r

In this example, we want the relationship to have a value, and since no such relationship can be found, a new node and relationship are created. Note that since we are not interested in the created node, we don’t name it.

Result
+-------------------------+
| r                       |
+-------------------------+
| :X[20]{since:"forever"} |
+-------------------------+
1 row
Nodes created: 1
Relationships created: 1
Properties set: 1

Describe complex pattern

The pattern described by CREATE UNIQUE can be separated by commas, just like in MATCH and CREATE.

Query
MATCH (root { name: 'root' })
CREATE UNIQUE (root)-[:FOO]->(x),(root)-[:BAR]->(x)
RETURN x

This example pattern uses two paths, separated by a comma.

Result
+------------+
| x          |
+------------+
| Node[20]{} |
+------------+
1 row
Nodes created: 1
Relationships created: 2