Constraints

1. Introduction

The following constraint types are available:

Unique node property constraints

Unique property constraints ensure that property values are unique for all nodes with a specific label. Unique constraints do not mean that all nodes have to have a unique value for the properties — nodes without the property are not subject to this rule.

Node property existence constraints

Node property existence constraints ensure that a property exists for all nodes with a specific label. Queries that try to create new nodes of the specified label, but without this property, will fail. The same is true for queries that try to remove the mandatory property.

Relationship property existence constraints

Property existence constraints ensure that a property exists for all relationships with a specific type. All queries that try to create relationships of the specified type, but without this property, will fail. The same is true for queries that try to remove the mandatory property.

Node key constraints

Node key constraints ensure that, for a given label and set of properties:

  1. All the properties exist on all the nodes with that label.

  2. The combination of the property values is unique.

Queries attempting to do any of the following will fail:

  • Create new nodes without all the properties or where the combination of property values is not unique.

  • Remove one of the mandatory properties.

  • Update the properties so that the combination of property values is no longer unique.

Node key constraints, node property existence constraints and relationship property existence constraints are only available in Neo4j Enterprise Edition. Databases containing one of these constraint types cannot be opened using Neo4j Community Edition.

Creating a constraint has the following implications on indexes:

  • Adding a unique property constraint on a property will also add a single-property index on that property, so such an index cannot be added separately.

  • Adding a node key constraint for a set of properties will also add a composite index on those properties, so such an index cannot be added separately.

  • Cypher will use these indexes for lookups just like other indexes. Refer to Indexes for search performance for more details on indexes.

  • If a unique property constraint is dropped and the single-property index on the property is still required, the index will need to be created explicitly.

  • If a node key constraint is dropped and the composite-property index on the properties is still required, the index will need to be created explicitly.

Additionally, the following is true for constraints:

  • A given label can have multiple constraints, and unique and property existence constraints can be combined on the same property.

  • Adding constraints is an atomic operation that can take a while — all existing data has to be scanned before Neo4j can turn the constraint 'on'.

  • Best practice is to give the constraint a name when it is created. If the constraint is not explicitly named, it will get an auto-generated name.

  • The constraint name must be unique among both indexes and constraints.

  • Constraint creation is by default not idempotent, and an error will be thrown if you attempt to create the same constraint twice. Using the keyword IF NOT EXISTS makes the command idempotent, and no error will be thrown if you attempt to create the same constraint twice.

2. Syntax

Table 1. Syntax for managing indexes
Command Description Comment
CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS]
ON (n:LabelName)
ASSERT n.propertyName IS UNIQUE
[OPTIONS "{" option: value[, ...] "}"]

Create a unique node property constraint.

Best practice is to give the constraint a name when it is created. If the constraint is not explicitly named, it will get an auto-generated name.

The constraint name must be unique among both indexes and constraints.

The command is optionally idempotent, with the default behavior to throw an error if you attempt to create the same constraint twice. With IF NOT EXISTS, no error is thrown and nothing happens should a constraint with the same name or same schema and constraint type already exist. It may still throw an error should a conflicting index or constraint exist.

Index provider and configuration for the backing index can be specified using the OPTIONS clause.

CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS]
ON (n:LabelName)
ASSERT EXISTS (n.propertyName)

Create a node property existence constraint.

CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS]
ON ()-"["R:RELATIONSHIP_TYPE"]"-()
ASSERT EXISTS (R.propertyName)

Create a relationship property existence constraint.

CREATE CONSTRAINT [constraint_name] [IF NOT EXISTS]
ON (n:LabelName)
ASSERT (n.propertyName_1,
n.propertyName_2,
…
n.propertyName_n)
IS NODE KEY
[OPTIONS "{" option: value[, ...] "}"]

Create a node key constraint.

DROP CONSTRAINT constraint_name [IF EXISTS]

Drop a constraint.

The command is optionally idempotent, with the default behavior to throw an error if you attempt to drop the same constraint twice. With IF EXISTS, no error is thrown and nothing happens should the constraint not exist.

SHOW [ALL|UNIQUE|NODE EXIST[S]|RELATIONSHIP EXIST[S]|EXIST[S]|NODE KEY] CONSTRAINT[S] [BRIEF|VERBOSE [OUTPUT]]

List constraints in the database, either all or filtered on type.

DROP CONSTRAINT
ON (n:LabelName)
ASSERT n.propertyName IS UNIQUE

Drop a unique constraint without specifying a name.

This syntax is deprecated.

DROP CONSTRAINT
ON (n:LabelName)
ASSERT EXISTS (n.propertyName)

Drop an exists constraint without specifying a name.

DROP CONSTRAINT
ON ()-"["R:RELATIONSHIP_TYPE"]"-()
ASSERT EXISTS (R.propertyName)

Drop a relationship property existence constraint without specifying a name.

DROP CONSTRAINT
ON (n:LabelName)
ASSERT (n.propertyName_1,
n.propertyName_2,
…
n.propertyName_n)
IS NODE KEY

Drop a node key constraint without specifying a name.

3. Examples

3.1. Unique node property constraints

3.1.1. Create a unique constraint

When creating a unique constraint, a name can be provided. The constraint ensures that your database will never contain more than one node with a specific label and one property value.

Query
CREATE CONSTRAINT constraint_name ON (book:Book) ASSERT book.isbn IS UNIQUE
+-------------------+
| No data returned. |
+-------------------+
Unique constraints added: 1

3.1.2. Create a unique constraint only if it does not already exist

If it is unknown if a constraint exists or not but we want to make sure it does, we add the IF NOT EXISTS. The uniqueness constraint ensures that your database will never contain more than one node with a specific label and one property value.

Query
CREATE CONSTRAINT constraint_name IF NOT EXISTS ON (book:Book) ASSERT book.isbn IS UNIQUE

Note no constraint will be created if any other constraint with that name or another uniqueness constraint on the same schema already exists. Assuming no such constraints existed:

+-------------------+
| No data returned. |
+-------------------+
Unique constraints added: 1

3.1.3. Create a unique constraint with specified index provider and configuration

To create a unique constraint with a specific index provider and configuration for the backing index, the OPTIONS clause is used. Valid values for the index provider is native-btree-1.0 and lucene+native-3.0, default if nothing is specified is native-btree-1.0. Valid configuration settings are spatial.cartesian.min, spatial.cartesian.max, spatial.cartesian-3d.min, spatial.cartesian-3d.max, spatial.wgs-84.min, spatial.wgs-84.max, spatial.wgs-84-3d.min, and spatial.wgs-84-3d.max. Non-specified settings get their respective default values.

Query
CREATE CONSTRAINT constraint_with_options ON (n:Label) ASSERT n.prop IS UNIQUE
OPTIONS {
 indexProvider: 'lucene+native-3.0',
 indexConfig: {`spatial.wgs-84.min`: [-100.0, -80.0], `spatial.wgs-84.max`: [100.0, 80.0]}
}

Specifying index provider and configuration can be done individually.

+-------------------+
| No data returned. |
+-------------------+
Unique constraints added: 1

3.1.4. Create a node that complies with unique property constraints

Create a Book node with an isbn that isn’t already in the database.

Query
CREATE (book:Book {isbn: '1449356265', title: 'Graph Databases'})
+-------------------+
| No data returned. |
+-------------------+
Nodes created: 1
Properties set: 2
Labels added: 1

3.1.5. Create a node that violates a unique property constraint

Create a Book node with an isbn that is already used in the database.

Query
CREATE (book:Book {isbn: '1449356265', title: 'Graph Databases'})

In this case the node isn’t created in the graph.

Error message
Node(0) already exists with label `Book` and property `isbn` = '1449356265'

3.1.6. Failure to create a unique property constraint due to conflicting nodes

Create a unique property constraint on the property isbn on nodes with the Book label when there are two nodes with the same isbn.

Query
CREATE CONSTRAINT ON (book:Book) ASSERT book.isbn IS UNIQUE

In this case the constraint can’t be created because it is violated by existing data. We may choose to use Indexes for search performance instead or remove the offending nodes and then re-apply the constraint.

Error message
Unable to create Constraint( name='constraint_ca412c3d', type='UNIQUENESS',
schema=(:Book {isbn}) ):
Both Node(0) and Node(1) have the label `Book` and property `isbn` = '1449356265'

3.2. Node property existence constraints

3.2.1. Create a node property existence constraint

When creating a node property existence constraint, a name can be provided. The constraint ensures that all nodes with a certain label have a certain property.

Query
CREATE CONSTRAINT constraint_name ON (book:Book) ASSERT exists(book.isbn)
+-------------------+
| No data returned. |
+-------------------+
Property existence constraints added: 1

3.2.2. Create a node property existence constraint only if it does not already exist

If it is unknown if a constraint exists or not but we want to make sure it does, we add the IF NOT EXISTS. The node property existence constraint ensures that all nodes with a certain label have a certain property.

Query
CREATE CONSTRAINT constraint_name IF NOT EXISTS ON (book:Book) ASSERT exists(book.isbn)

Note no constraint will be created if any other constraint with that name or another node property existence constraint on the same schema already exists. Assuming a constraint with the name constraint_name already existed:

+--------------------------------------------+
| No data returned, and nothing was changed. |
+--------------------------------------------+

3.2.3. Create a node that complies with property existence constraints

Create a Book node with an isbn property.

Query
CREATE (book:Book {isbn: '1449356265', title: 'Graph Databases'})
+-------------------+
| No data returned. |
+-------------------+
Nodes created: 1
Properties set: 2
Labels added: 1

3.2.4. Create a node that violates a property existence constraint

Trying to create a Book node without an isbn property, given a property existence constraint on :Book(isbn).

Query
CREATE (book:Book {title: 'Graph Databases'})

In this case the node isn’t created in the graph.

Error message
Node(0) with label `Book` must have the property `isbn`

3.2.5. Removing an existence constrained node property

Trying to remove the isbn property from an existing node book, given a property existence constraint on :Book(isbn).

Query
MATCH (book:Book {title: 'Graph Databases'}) REMOVE book.isbn

In this case the property is not removed.

Error message
Node(0) with label `Book` must have the property `isbn`

3.2.6. Failure to create a node property existence constraint due to existing node

Create a constraint on the property isbn on nodes with the Book label when there already exists a node without an isbn.

Query
CREATE CONSTRAINT ON (book:Book) ASSERT exists(book.isbn)

In this case the constraint can’t be created because it is violated by existing data. We may choose to remove the offending nodes and then re-apply the constraint.

Error message
Unable to create Constraint( type='NODE PROPERTY EXISTENCE', schema=(:Book
{isbn}) ):
Node(0) with label `Book` must have the property `isbn`

3.3. Relationship property existence constraints

3.3.1. Create a relationship property existence constraint

When creating a relationship property existence constraint, a name can be provided. The constraint ensures all relationships with a certain type have a certain property.

Query
CREATE CONSTRAINT constraint_name ON ()-[like:LIKED]-() ASSERT exists(like.day)
+-------------------+
| No data returned. |
+-------------------+
Property existence constraints added: 1

3.3.2. Create a relationship property existence constraint only if it does not already exist

If it is unknown if a constraint exists or not but we want to make sure it does, we add the IF NOT EXISTS. The relationship property existence constraint ensures all relationships with a certain type have a certain property.

Query
CREATE CONSTRAINT constraint_name IF NOT EXISTS ON ()-[like:LIKED]-() ASSERT exists(like.day)

Note no constraint will be created if any other constraint with that name or another relationship property existence constraint on the same schema already exists. Assuming a constraint with the name constraint_name already existed:

+--------------------------------------------+
| No data returned, and nothing was changed. |
+--------------------------------------------+

3.3.3. Create a relationship that complies with property existence constraints

Create a LIKED relationship with a day property.

Query
CREATE (user:User)-[like:LIKED {day: 'yesterday'}]->(book:Book)
+-------------------+
| No data returned. |
+-------------------+
Nodes created: 2
Relationships created: 1
Properties set: 1
Labels added: 2

3.3.4. Create a relationship that violates a property existence constraint

Trying to create a LIKED relationship without a day property, given a property existence constraint :LIKED(day).

Query
CREATE (user:User)-[like:LIKED]->(book:Book)

In this case the relationship isn’t created in the graph.

Error message
Relationship(0) with type `LIKED` must have the property `day`

3.3.5. Removing an existence constrained relationship property

Trying to remove the day property from an existing relationship like of type LIKED, given a property existence constraint :LIKED(day).

Query
MATCH (user:User)-[like:LIKED]->(book:Book) REMOVE like.day

In this case the property is not removed.

Error message
Relationship(0) with type `LIKED` must have the property `day`

3.3.6. Failure to create a relationship property existence constraint due to existing relationship

Create a constraint on the property day on relationships with the LIKED type when there already exists a relationship without a property named day.

Query
CREATE CONSTRAINT ON ()-[like:LIKED]-() ASSERT exists(like.day)

In this case the constraint can’t be created because it is violated by existing data. We may choose to remove the offending relationships and then re-apply the constraint.

Error message
Unable to create Constraint( type='RELATIONSHIP PROPERTY EXISTENCE',
schema=-[:LIKED {day}]- ):
Relationship(0) with type `LIKED` must have the property `day`

3.4. Node key constraints

3.4.1. Create a node key constraint

When creating a node key constraint, a name can be provided. The constraint ensures that all nodes with a particular label have a set of defined properties whose combined value is unique and all properties in the set are present.

Query
CREATE CONSTRAINT constraint_name ON (n:Person) ASSERT (n.firstname, n.surname) IS NODE KEY
+-------------------+
| No data returned. |
+-------------------+
Node key constraints added: 1

3.4.2. Create a node key constraint only if it does not already exist

If it is unknown if a constraint exists or not but we want to make sure it does, we add the IF NOT EXISTS. The node key constraint ensures that all nodes with a particular label have a set of defined properties whose combined value is unique and all properties in the set are present.

Query
CREATE CONSTRAINT constraint_name IF NOT EXISTS ON (n:Person) ASSERT (n.firstname,
  n.surname) IS NODE KEY

Note no constraint will be created if any other constraint with that name or another node key constraint on the same schema already exists. Assuming a node key constraint on (:Person {firstname, surname}) already existed:

+--------------------------------------------+
| No data returned, and nothing was changed. |
+--------------------------------------------+

3.4.3. Create a node key constraint with specified index provider

To create a node key constraint with a specific index provider for the backing index, the OPTIONS clause is used. Valid values for the index provider is native-btree-1.0 and lucene+native-3.0, default if nothing is specified is native-btree-1.0.

Query
CREATE CONSTRAINT constraint_with_provider ON (n:Label) ASSERT (n.prop1) IS NODE KEY OPTIONS
  {indexProvider: 'native-btree-1.0'}

Can be combined with specifying index configuration.

+-------------------+
| No data returned. |
+-------------------+
Node key constraints added: 1

3.4.4. Create a node key constraint with specified index configuration

To create a node key constraint with a specific index configuration for the backing index, the OPTIONS clause is used. Valid configuration settings are spatial.cartesian.min, spatial.cartesian.max, spatial.cartesian-3d.min, spatial.cartesian-3d.max, spatial.wgs-84.min, spatial.wgs-84.max, spatial.wgs-84-3d.min, and spatial.wgs-84-3d.max. Non-specified settings get their respective default values.

Query
CREATE CONSTRAINT constraint_with_config ON (n:Label) ASSERT (n.prop2) IS NODE KEY
OPTIONS {indexConfig: {`spatial.cartesian.min`: [-100.0, -100.0], `spatial.cartesian.max`: [100.0,
  100.0]}}

Can be combined with specifying index provider.

+-------------------+
| No data returned. |
+-------------------+
Node key constraints added: 1

3.4.5. Create a node that complies with node key constraints

Create a Person node with both a firstname and surname property.

Query
CREATE (p:Person {firstname: 'John', surname: 'Wood', age: 55})
+-------------------+
| No data returned. |
+-------------------+
Nodes created: 1
Properties set: 3
Labels added: 1

3.4.6. Create a node that violates a node key constraint

Trying to create a Person node without a surname property, given a node key constraint on :Person(firstname, surname), will fail.

Query
CREATE (p:Person {firstname: 'Jane', age: 34})

In this case the node isn’t created in the graph.

Error message
Node(0) with label `Person` must have the properties (firstname, surname)

3.4.7. Removing a NODE KEY-constrained property

Trying to remove the surname property from an existing node Person, given a NODE KEY constraint on :Person(firstname, surname).

Query
MATCH (p:Person {firstname: 'John', surname: 'Wood'}) REMOVE p.surname

In this case the property is not removed.

Error message
Node(0) with label `Person` must have the properties (firstname, surname)

3.4.8. Failure to create a node key constraint due to existing node

Trying to create a node key constraint on the property surname on nodes with the Person label will fail when a node without a surname already exists in the database.

Query
CREATE CONSTRAINT ON (n:Person) ASSERT (n.firstname, n.surname) IS NODE KEY

In this case the node key constraint can’t be created because it is violated by existing data. We may choose to remove the offending nodes and then re-apply the constraint.

Error message
Unable to create Constraint( type='NODE PROPERTY EXISTENCE', schema=(:Person
{firstname, surname}) ):
Node(0) with label `Person` must have the properties (firstname, surname)

3.5. Drop a constraint by name

3.5.1. Drop a constraint

A constraint can be dropped using the name with the DROP CONSTRAINT constraint_name command. It is the same command for unique property, property existence and node key constraints. The name of the constraint can be found using the SHOW CONSTRAINTS command, given in the output column name.

Query
DROP CONSTRAINT constraint_name
+-------------------+
| No data returned. |
+-------------------+
Named constraints removed: 1

3.5.2. Drop a non-existing constraint

If it is uncertain if any constraint with a given name exists and you want to drop it if it does but not get an error should it not, use IF EXISTS. It is the same command for unique property, property existence and node key constraints.

Query
DROP CONSTRAINT missing_constraint_name IF EXISTS
+--------------------------------------------+
| No data returned, and nothing was changed. |
+--------------------------------------------+

3.6. List constraints

Listing constraints can be done with SHOW CONSTRAINTS, which will produce a table with the following columns:

Table 2. List constraints output
Column Description Brief output Verbose output

id

The id of the constraint.

+

+

name

Name of the constraint (explicitly set by the user or automatically assigned).

+

+

type

The ConstraintType of this constraint (UNIQUENESS, NODE_PROPERTY_EXISTENCE, NODE_KEY, or RELATIONSHIP_PROPERTY_EXISTENCE).

+

+

entityType

Type of entities this constraint represents (nodes or relationship).

+

+

labelsOrTypes

The labels or relationship types of this constraint.

+

+

properties

The properties of this constraint.

+

+

ownedIndexId

The id of the index associated to the constraint, or null if no index is associated with the constraint.

+

+

options

The options passed to CREATE command, for the index associated to the constraint, or null if no index is associated with the constraint.

+

createStatement

Statement used to create the constraint.

+

The deprecated built-in procedures for listing constraints, such as db.constraints, work as before and are not affected by the SHOW CONSTRAINTS privilege.

3.6.1. Example of listing constraints

To list all constraints with the brief output columns, the SHOW CONSTRAINTS command can be used. If all columns are wanted, use SHOW CONSTRAINTS VERBOSE. Filtering the output on constraint type is available for all types, the filtering keywords are listed in the syntax table. As an example, to show only unique constraints, use SHOW UNIQUE CONSTRAINTS.

Query
SHOW CONSTRAINTS

One of the output columns from SHOW CONSTRAINTS is the name of the constraint. This can be used to drop the constraint with the DROP CONSTRAINT command.

+----------------------------------------------------------------------------------------------------+
| id | name                  | type         | entityType | labelsOrTypes | properties | ownedIndexId |
+----------------------------------------------------------------------------------------------------+
| 2  | "constraint_ca412c3d" | "UNIQUENESS" | "NODE"     | ["Book"]      | ["isbn"]   | 1            |
+----------------------------------------------------------------------------------------------------+
1 row

3.7. Deprecated syntax

3.7.1. Drop a unique constraint

By using DROP CONSTRAINT, you remove a constraint from the database.

Query
DROP CONSTRAINT ON (book:Book) ASSERT book.isbn IS UNIQUE
+-------------------+
| No data returned. |
+-------------------+
Unique constraints removed: 1

3.7.2. Drop a node property existence constraint

By using DROP CONSTRAINT, you remove a constraint from the database.

Query
DROP CONSTRAINT ON (book:Book) ASSERT exists(book.isbn)
+-------------------+
| No data returned. |
+-------------------+
Property existence constraints removed: 1

3.7.3. Drop a relationship property existence constraint

To remove a constraint from the database, use DROP CONSTRAINT.

Query
DROP CONSTRAINT ON ()-[like:LIKED]-() ASSERT exists(like.day)
+-------------------+
| No data returned. |
+-------------------+
Property existence constraints removed: 1

3.7.4. Drop a node key constraint

Use DROP CONSTRAINT to remove a node key constraint from the database.

Query
DROP CONSTRAINT ON (n:Person) ASSERT (n.firstname, n.surname) IS NODE KEY
+-------------------+
| No data returned. |
+-------------------+
Node key constraints removed: 1