Examples

This page contains examples of how to manage constraints used for ensuring data integrity.

Node property uniqueness constraints

A node property uniqueness constraint ensures that certain nodes have a set of specified properties whose combined value is unique when all properties exist on the node.

Create a node property uniqueness constraint

When creating a property uniqueness constraint, it is recommended to provide a constraint name.

Example 1. CREATE CONSTRAINT
Query
CREATE CONSTRAINT book_isbn
FOR (book:Book) REQUIRE book.isbn IS UNIQUE
Result
Added 1 constraint.

The detailed statistics view currently says Unique constraints added: 1. It will be updated to say Node property uniqueness constraints added: 1 in Neo4j 6.0.

Create a node property uniqueness constraint using a parameter

The constraint name can also be given as a parameter.

Example 2. CREATE CONSTRAINT
Parameters
{
  "name": "node_uniqueness_param"
}
Query
CREATE CONSTRAINT $name
FOR (book:Book) REQUIRE book.prop1 IS UNIQUE
Result
Added 1 constraint.

The detailed statistics view currently says Unique constraints added: 1. It will be updated to say Node property uniqueness constraints added: 1 in Neo4j 6.0.

Handling existing constraints when creating a constraint

Creating an already existing constraint will fail. To avoid such an error, IF NOT EXISTS can be added to the CREATE command. This will ensure that no error is thrown and that no constraint is created if any other constraint with the given name, or another node property uniqueness constraint on the same schema, already exists. Introduced in 5.17 An informational notification is instead returned showing the existing constraint which blocks the creation.

Example 3. CREATE CONSTRAINT
Query
CREATE CONSTRAINT book_isbn2 IF NOT EXISTS
FOR (book:Book) REQUIRE book.isbn2 IS UNIQUE

Assuming no constraint with the given name or other node property uniqueness constraint on the same schema already exists, the query will return:

Result
Added 1 constraint.

The detailed statistics view currently says Unique constraints added: 1. It will be updated to say Node property uniqueness constraints added: 1 in Neo4j 6.0.

Specifying an index provider when creating a constraint

To create a property uniqueness constraint with a specific index provider for the backing index, the OPTIONS clause is used.

The index type of the backing index is set with the indexProvider option.

The only valid value for the index provider is:

  • range-1.0 Default

Example 4. CREATE CONSTRAINT
Query
CREATE CONSTRAINT constraint_with_options
FOR (book:Book) REQUIRE (book.prop1, book.prop2) IS UNIQUE
OPTIONS {
  indexProvider: 'range-1.0'
}
Result
Added 1 constraint.

The detailed statistics view currently says Unique constraints added: 1. It will be updated to say Node property uniqueness constraints added: 1 in Neo4j 6.0.

There is no valid index configuration values for the constraint-backing range indexes.

Creating an already existing constraint will fail

Example 5. CREATE CONSTRAINT

Create a property uniqueness constraint on the property published on nodes with the Book label, when that constraint already exists:

Query
CREATE CONSTRAINT book_published FOR (book:Book) REQUIRE book.published IS UNIQUE

In this case, the constraint cannot be created because it already exists.

Error message
Constraint already exists:
Constraint( id=4, name='preExisting_book_published', type='UNIQUENESS', schema=(:Book {published}), ownedIndex=3 )

The constraint type will be updated to say NODE PROPERTY UNIQUENESS in Neo4j 6.0.

Creating a constraint on the same schema as an existing index will fail

Example 6. CREATE CONSTRAINT

Create a property uniqueness constraint on the property wordCount on nodes with the Book label, when an index already exists on that label and property combination:

Query
CREATE CONSTRAINT book_word_count FOR (book:Book) REQUIRE book.wordCount IS UNIQUE

In this case, the constraint cannot be created because there already exists an index covering that schema.

Error message
There already exists an index (:Book {wordCount}).
A constraint cannot be created until the index has been dropped.

Creating a node that complies with an existing constraint

Example 7. CREATE NODE

Create a Book node with an isbn that is not already in the graph:

Query
CREATE (book:Book {isbn: '1449356265', title: 'Graph Databases'})
Result
Added 1 label, created 1 node, set 2 properties

Creating a node that violates an existing constraint will fail

Example 8. CREATE NODE

Create a Book node with an isbn that is already used in the graph:

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

In this case, the node is not created because the isbn property is in conflict with an existing constraint.

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

Creating a constraint when there exist conflicting nodes will fail

Example 9. CREATE CONSTRAINT

Create a property uniqueness constraint on the property title on nodes with the Book label, when there are two nodes with the same title:

Query
CREATE CONSTRAINT book_title FOR (book:Book) REQUIRE book.title IS UNIQUE

In this case, the constraint cannot be created because it is in conflict with the existing graph. Either use Create, show, and delete indexes instead, or remove/correct the offending nodes and then re-apply the constraint.

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

The constraint type will be updated to say NODE PROPERTY UNIQUENESS in Neo4j 6.0.

The constraint creation fails on the first offending nodes that are found. This does not guarantee that there are no other offending nodes in the graph. Therefore, all the data should be checked and cleaned up before re-attempting the constraint creation.

This is an example MATCH query to find all offending nodes with the non-unique property values for the constraint above:

Query
MATCH (book1:Book), (book2:Book)
WHERE book1.title = book2.title AND NOT book1 = book2
RETURN book1, book2

Relationship property uniqueness constraints

This feature was introduced in Neo4j 5.7.

A relationship property uniqueness constraint ensures that certain relationships have a set of specified properties whose combined value is unique when all properties exist on the relationship.

Create a relationship property uniqueness constraint

When creating a property uniqueness constraint, it is recommended to provide a constraint name.

Example 10. CREATE CONSTRAINT
Query
CREATE CONSTRAINT sequels
FOR ()-[sequel:SEQUEL_OF]-() REQUIRE (sequel.order, sequel.seriesTitle) IS UNIQUE
Result
Added 1 constraint.

The detailed statistics view currently says Relationship uniqueness constraints added: 1. It will be updated to say Relationship property uniqueness constraints added: 1 in Neo4j 6.0.

Create a relationship property uniqueness constraint using a parameter

The constraint name can also be given as a parameter.

Example 11. CREATE CONSTRAINT
Parameters
{
  "name": "rel_uniqueness_param"
}
Query
CREATE CONSTRAINT $name
FOR ()-[sequel:SEQUEL_OF]-() REQUIRE (sequel.prop1) IS UNIQUE
Result
Added 1 constraint.

The detailed statistics view currently says Relationship uniqueness constraints added: 1. It will be updated to say Relationship property uniqueness constraints added: 1 in Neo4j 6.0.

Handling existing constraints when creating a constraint

Creating an already existing constraint will fail. To avoid such an error, IF NOT EXISTS can be added to the CREATE command. This will ensure that no error is thrown and that no constraint is created if any other constraint with the given name, or another relationship property uniqueness constraint on the same schema, already exists. Introduced in 5.17 An informational notification is instead returned showing the existing constraint which blocks the creation.

Example 12. CREATE CONSTRAINT
Query
CREATE CONSTRAINT sequels IF NOT EXISTS
FOR ()-[sequel:SEQUEL_OF]-() REQUIRE (sequel.order) IS UNIQUE

Assuming a constraint with the name sequels already exists:

Result
(no changes, no records)
Notification
`CREATE CONSTRAINT sequels IF NOT EXISTS FOR ()-[e:SEQUEL_OF]-() REQUIRE (e.order) IS UNIQUE` has no effect.
`CONSTRAINT sequels FOR ()-[e:SEQUEL_OF]-() REQUIRE (e.order, e.seriesTitle) IS UNIQUE` already exists.

The detailed statistics view currently says Relationship uniqueness constraints added: 1. It will be updated to say Relationship property uniqueness constraints added: 1 in Neo4j 6.0.

Specifying an index provider when creating a constraint

To create a property uniqueness constraint with a specific index provider for the backing index, the OPTIONS clause is used.

The index type of the backing index is set with the indexProvider option.

The only valid value for the index provider is:

  • range-1.0 Default

Example 13. CREATE CONSTRAINT
Query
CREATE CONSTRAINT rel_constraint_with_options
FOR ()-[sequel:SEQUEL_OF]-() REQUIRE (sequel.order, sequel.seriesTitle, sequel.number) IS UNIQUE
OPTIONS {
  indexProvider: 'range-1.0'
}
Result
Added 1 constraint.

The detailed statistics view currently says Relationship uniqueness constraints added: 1. It will be updated to say Relationship property uniqueness constraints added: 1 in Neo4j 6.0.

There are no valid index configuration values for the constraint-backing range indexes.

Creating an already existing constraint will fail

Example 14. CREATE CONSTRAINT

Create a property uniqueness constraint on the properties order and seriesTitle on relationships with the SEQUEL_OF relationship type, when that constraint already exists:

Query
CREATE CONSTRAINT sequel_order_seriestitle FOR ()-[sequel:SEQUEL_OF]-() REQUIRE (sequel.order, sequel.seriesTitle) IS UNIQUE

In this case, the constraint cannot be created because it already exists.

Error message
Constraint already exists:
Constraint( id=13, name='sequels', type='RELATIONSHIP UNIQUENESS', schema=()-[:SEQUEL_OF {order, seriesTitle}]-(), ownedIndex=12 )

The constraint type will be updated to say RELATIONSHIP PROPERTY UNIQUENESS in Neo4j 6.0.

Creating a constraint on the same schema as an existing index will fail

Example 15. CREATE CONSTRAINT

Create a property uniqueness constraint on the property order on relationships with the SEQUEL_OF relationship type, when an index already exists on that relationship type and property combination:

Query
CREATE CONSTRAINT sequel_series_title FOR ()-[sequel:SEQUEL_OF]-() REQUIRE (sequel.order) IS UNIQUE

In this case, the constraint cannot be created because there already exists an index covering that schema.

Error message
There already exists an index ()-[:SEQUEL_OF {order}]-().
A constraint cannot be created until the index has been dropped.

Creating a relationship that complies with an existing constraint

Example 16. CREATE RELATIONSHIP

Create a SEQUEL_OF relationship with values for properties order and seriesTitle that are not already in the graph:

Query
CREATE (:Book {title: 'Spirit Walker'})-[:SEQUEL_OF {order: 1, seriesTitle: 'Chronicles of Ancient Darkness'}]->(:Book {title: 'Wolf Brother'})
Result
Added 2 labels, created 2 nodes, set 4 properties, created 1 relationship.

Creating a relationship that violates an existing constraint will fail

Example 17. CREATE RELATIONSHIP

Create a SEQUEL_OF relationship with values for properties order and seriesTitle that are already used in the graph:

Query
MATCH (wolfBrother:Book {title: 'Wolf Brother'}), (spiritWalker:Book {title: 'Spirit Walker'})
CREATE (spiritWalker)-[:SEQUEL_OF {order: 1, seriesTitle: 'Chronicles of Ancient Darkness'}]->(wolfBrother)

In this case, the relationship is not created because the combination of the order and seriesTitle properties are in conflict with an existing constraint.

Error message
Relationship(0) already exists with type `SEQUEL_OF` and properties `order` = 1, `seriesTitle` = 'Chronicles of Ancient Darkness'

Creating a constraint when there exist conflicting relationships will fail

Example 18. CREATE CONSTRAINT

Create a property uniqueness constraint on the property seriesTitle on relationships with the SEQUEL_OF relationship type, when two relationships with the same seriesTitle already exist:

Query
CREATE CONSTRAINT series_title FOR ()-[sequel:SEQUEL_OF]-() REQUIRE (sequel.seriesTitle) IS UNIQUE

In this case, the constraint cannot be created because it is in conflict with the existing graph. Either use Create, show, and delete indexes instead, or remove/correct the offending relationships and then re-apply the constraint.

Error message
Unable to create Constraint( name='series_title', type='RELATIONSHIP UNIQUENESS', schema=()-[:SEQUEL_OF {seriesTitle}]-() ):
Both Relationship(0) and Relationship(1) have the type `SEQUEL_OF` and property `seriesTitle` = 'Chronicles of Ancient Darkness'

The constraint creation fails on the first offending relationships that are found. This does not guarantee that there are no other offending relationships in the graph. Therefore, all the data should be checked and cleaned up before re-attempting the constraint creation.

This is an example MATCH query to find all offending relationships for the constraint above:

Query
MATCH ()-[knows1:KNOWS]->(), ()-[knows2:KNOWS]->()
WHERE knows1.level = knows2.level AND NOT knows1 = knows2
RETURN knows1, knows2

Node property existence constraints

A node property existence constraint ensures that certain nodes have a specified property.

Create a node property existence constraint

When creating a node property existence constraint, it is recommended to provide a constraint name.

Example 19. CREATE CONSTRAINT
Query
CREATE CONSTRAINT author_name
FOR (author:Author) REQUIRE author.name IS NOT NULL
Result
Added 1 constraint.

The detailed statistics view for property existence constraints, Property existence constraints added: 1, will be split between nodes and relationships in Neo4j 6.0. For the node property existence constraints, they will say Node property existence constraints added: 1.

Create a node property existence constraint using a parameter

The constraint name can also be given as a parameter.

Example 20. CREATE CONSTRAINT
Parameters
{
  "name": "node_exist_param"
}
Query
CREATE CONSTRAINT $name
FOR (author:Author) REQUIRE author.surname IS NOT NULL
Result
Added 1 constraint.

The detailed statistics view for property existence constraints, Property existence constraints added: 1, will be split between nodes and relationships in Neo4j 6.0. For the node property existence constraints, they will say Node property existence constraints added: 1.

Handling existing constraints when creating a constraint

Creating an already existing constraint will fail. To avoid such an error, IF NOT EXISTS can be added to the CREATE command. This will ensure that no error is thrown and that no constraint is created if any other constraint with the given name, or another node property existence constraint on the same schema, already exists. Introduced in 5.17 An informational notification is instead returned showing the existing constraint which blocks the creation.

Example 21. CREATE CONSTRAINT
Query
CREATE CONSTRAINT author_pseudonym IF NOT EXISTS
FOR (author:Author) REQUIRE author.pseudonym IS NOT NULL

Assuming a constraint with the name author_pseudonym already exists:

Result
(no changes, no records)
Notification
`CREATE CONSTRAINT author_pseudonym IF NOT EXISTS FOR (e:Author) REQUIRE (e.pseudonym) IS NOT NULL` has no effect.
`CONSTRAINT author_pseudonym FOR (e:Author) REQUIRE (e.pseudonym) IS UNIQUE` already exists.

Creating an already existing constraint will fail

Example 22. CREATE CONSTRAINT

Create a node property existence constraint on the property name on nodes with the Author label, when that constraint already exists:

Query
CREATE CONSTRAINT author_name
FOR (author:Author) REQUIRE author.name IS NOT NULL

In this case, the constraint cannot be created because it already exists.

Error message
An equivalent constraint already exists, 'Constraint( id=10, name='author_name', type='NODE PROPERTY EXISTENCE', schema=(:Author {name}) )'.

Creating a node that complies with an existing constraint

Example 23. CREATE NODE

Create an Author node with a name property:

Query
CREATE (author:Author {name:'Virginia Woolf', surname: 'Woolf'})
Result
Added 1 label, created 1 node, set 2 properties

Creating a node that violates an existing constraint will fail

Example 24. CREATE NODE

Create an Author node without a name property, given a property existence constraint on :Author(name):

Query
CREATE (author:Author {surname: 'Austen'})

In this case, the node is not created because it is missing the name property which is in conflict with an existing constraint.

Error message
Node(0) with label `Author` must have the property `name`

Removing an existence constrained node property will fail

Example 25. REMOVE PROPERTY

Remove the name property from an existing node Author, given a property existence constraint on :Author(name):

Query
MATCH (author:Author {name: 'Virginia Woolf'})
REMOVE author.name

In this case, the property is not removed because it is in conflict with an existing constraint.

Error message
Node(0) with label `Author` must have the property `name`

Creating a constraint when there exist conflicting nodes will fail

Example 26. CREATE CONSTRAINT

Create a constraint on the property nationality on nodes with the Author label, when there already exists a node without a nationality property:

Query
CREATE CONSTRAINT author_nationality FOR (author:Author) REQUIRE author.nationality IS NOT NULL

In this case, the constraint cannot be created because it is in conflict with the existing graph. Remove or correct the offending nodes and then re-apply the constraint.

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

The constraint creation fails on the first offending node that is found. This does not guarantee that there are no other offending nodes in the graph. Therefore, all the data should be checked and cleaned up before re-attempting the constraint creation.

This is an example MATCH query to find all offending nodes missing the property for the constraint above:

Query
MATCH (author:Author)
WHERE author.nationality IS NULL
RETURN author

Relationship property existence constraints

A relationship property existence constraint ensures that certain relationships have a certain property.

Create a relationship property existence constraint

When creating a relationship property existence constraint, it is recommended to provide a constraint name.

Example 27. CREATE CONSTRAINT
Query
CREATE CONSTRAINT wrote_year
FOR ()-[wrote:WROTE]-() REQUIRE wrote.year IS NOT NULL
Result
Added 1 constraint.

The detailed statistics view for property existence constraints, Property existence constraints added: 1, will be split between nodes and relationships in Neo4j 6.0. For the relationship property existence constraints, they will say Relationship property existence constraints added: 1.

Create a relationship property existence constraint using a parameter

The constraint name can also be given as a parameter.

Example 28. CREATE CONSTRAINT
Parameters
{
  "name": "rel_exist_param"
}
Query
CREATE CONSTRAINT $name
FOR ()-[wrote:WROTE]-() REQUIRE wrote.published IS NOT NULL
Result
Added 1 constraint.

The detailed statistics view for property existence constraints, Property existence constraints added: 1, will be split between nodes and relationships in Neo4j 6.0. For the relationship property existence constraints, they will say Relationship property existence constraints added: 1.

Handling existing constraints when creating a constraint

Creating an already existing constraint will fail. To avoid such an error, IF NOT EXISTS can be added to the CREATE command. This will ensure that no error is thrown and that no constraint is created if any other constraint with the given name, or another relationship property existence constraint on the same schema, already exists. Introduced in 5.17 An informational notification is instead returned showing the existing constraint which blocks the creation.

Example 29. CREATE CONSTRAINT
Query
CREATE CONSTRAINT wrote_year IF NOT EXISTS
FOR ()-[wrote:WROTE]-() REQUIRE wrote.year IS NOT NULL

Assuming that such a constraint already exists:

Result
(no changes, no records)
Notification
`CREATE CONSTRAINT wrote_year IF NOT EXISTS FOR ()-[e:WROTE]-() REQUIRE (e.year) IS NOT NULL` has no effect.
`CONSTRAINT wrote_year FOR ()-[e:WROTE]-() REQUIRE (e.year) IS NOT NULL` already exists.

Creating an already existing constraint will fail

Example 30. CREATE CONSTRAINT

Create a named relationship property existence constraint on the property locations on relationships with the WROTE relationship type, when a constraint with the given name already exists:

Query
CREATE CONSTRAINT wrote_locations
FOR ()-[wrote:WROTE]-() REQUIRE wrote.locations IS NOT NULL

In this case, the constraint cannot be created because there already exists a constraint with the given name.

Error message
There already exists a constraint called 'wrote_locations'.

Creating a relationship that complies with an existing constraint

Example 31. CREATE RELATIONSHIP

Create a WROTE relationship with a year and location property, given property existence constraints on :WROTE(year) and :WROTE(location):

Query
CREATE (author:Author {name: 'Emily Brontë', surname: 'Brontë'})-[wrote:WROTE {year: 1847, location: 'Haworth, United Kingdom', published: true}]->(book:Book {title:'Wuthering Heights', isbn: 9789186579296})
Result
Added 2 labels, created 2 nodes, set 7 properties, created 1 relationship

Creating a relationship that violates an existing constraint will fail

Example 32. CREATE RELATIONSHIP

Create a WROTE relationship without a location property, given a property existence constraint :WROTE(location):

Query
CREATE (author:Author {name: 'Charlotte Brontë', surname: 'Brontë'})-[wrote:WROTE {year: 1847, published: true}]->(book:Book {title: 'Jane Eyre', isbn:9780194241762})

In this case, the relationship is not created because it is missing the location property which is in conflict with an existing constraint.

Error message
Relationship(0) with type `WROTE` must have the property `location`

Removing an existence constrained relationship property will fail

Example 33. REMOVE PROPERTY

Remove the location property from an existing relationship of relationship type WROTE, given a property existence constraint :WROTE(location):

Query
MATCH (author:Author)-[wrote:WROTE]->(book:Book) REMOVE wrote.location

In this case, the property is not removed because it is in conflict with an existing constraint.

Error message
Relationship(0) with type `WROTE` must have the property `location`

Creating a constraint when there exist conflicting relationships will fail

Example 34. CREATE CONSTRAINT

Create a constraint on the property language on relationships with the WROTE relationship type, when there already exists a relationship without a property named language:

Query
CREATE CONSTRAINT wrote_language FOR ()-[wrote:WROTE]-() REQUIRE wrote.language IS NOT NULL

In this case, the constraint cannot be created because it is in conflict with the existing graph. Remove or correct the offending relationships and then re-apply the constraint.

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

The constraint creation fails on the first offending relationship that is found. This does not guarantee that there are no other offending relationships in the graph. Therefore, all the data should be checked and cleaned up before re-attempting the constraint creation.

This is an example MATCH query to find all offending relationships missing the property for the constraint above:

Query
MATCH ()-[wrote:WROTE]-()
WHERE wrote.language IS NULL
RETURN wrote

Node property type constraints

This feature was introduced in Neo4j 5.9.

A node property type constraint ensures that certain nodes have a property of the required property type when the property exists on the node.

The allowed property types for the constraints are:

  • BOOLEAN

  • STRING

  • INTEGER

  • FLOAT

  • DATE

  • LOCAL TIME

  • ZONED TIME

  • LOCAL DATETIME

  • ZONED DATETIME

  • DURATION

  • POINT

  • LIST<BOOLEAN NOT NULL> Introduced in 5.10

  • LIST<STRING NOT NULL> Introduced in 5.10

  • LIST<INTEGER NOT NULL> Introduced in 5.10

  • LIST<FLOAT NOT NULL> Introduced in 5.10

  • LIST<DATE NOT NULL> Introduced in 5.10

  • LIST<LOCAL TIME NOT NULL> Introduced in 5.10

  • LIST<ZONED TIME NOT NULL> Introduced in 5.10

  • LIST<LOCAL DATETIME NOT NULL> Introduced in 5.10

  • LIST<ZONED DATETIME NOT NULL> Introduced in 5.10

  • LIST<DURATION NOT NULL> Introduced in 5.10

  • LIST<POINT NOT NULL> Introduced in 5.10

  • Any closed dynamic union of the above types, e.g. INTEGER | FLOAT | STRING. Introduced in 5.11

For all available Cypher® types, see the section on types and their synonyms.

Create a node property type constraint

When creating a node property type constraint, it is recommended to provide a constraint name.

Example 35. CREATE CONSTRAINT
Query
CREATE CONSTRAINT movie_title
FOR (movie:Movie) REQUIRE movie.title IS :: STRING
Result
Added 1 constraint.

Create a node property type constraint using a parameter

The constraint name can also be given as a parameter.

Example 36. CREATE CONSTRAINT
Parameters
{
  "name": "node_prop_type_param"
}
Query
CREATE CONSTRAINT $name
FOR (movie:Movie) REQUIRE movie.prop1 IS :: INT
Result
Added 1 constraint.

Create a node property type constraint with a union type

This feature was introduced in Neo4j 5.11.

A closed dynamic union allows a node property to maintain some type flexibility whilst preventing unexpected values from being stored.

Example 37. CREATE CONSTRAINT
Query
CREATE CONSTRAINT movie_tagline
FOR (movie:Movie) REQUIRE movie.tagline IS :: STRING | LIST<STRING NOT NULL>
Result
Added 1 constraint.

Handling existing constraints when creating a constraint

Creating an already existing constraint will fail. To avoid such an error, IF NOT EXISTS can be added to the CREATE command. This will ensure that no error is thrown and that no constraint is created if any other constraint with the given name, or another node property type constraint on the same schema and property type, already exists. Introduced in 5.17 An informational notification is instead returned showing the existing constraint which blocks the creation.

Example 38. CREATE CONSTRAINT
Query
CREATE CONSTRAINT movie_titles IF NOT EXISTS
FOR (movie:Movie) REQUIRE movie.title :: STRING

Assuming a node property type constraint on the label Movie which restricts the property title to STRING values already exists:

Result
(no changes, no records)
Notification
`CREATE CONSTRAINT movie_titles IF NOT EXISTS FOR (e:Movie) REQUIRE (e.title) IS :: STRING` has no effect.
`CONSTRAINT movie_title FOR (e:Movie) REQUIRE e.title IS :: STRING` already exists.

Creating an already existing constraint will fail

Example 39. CREATE CONSTRAINT

Create a node property type constraint restricting the property title to STRING values on nodes with the Movie label, when that constraint already exists:

Query
CREATE CONSTRAINT movies
FOR (movie:Movie) REQUIRE movie.title IS TYPED STRING

In this case, the constraint cannot be created because it already exists.

Error message
Constraint already exists: Constraint( id=22, name='movie_title', type='NODE PROPERTY TYPE', schema=(:Movie {title}), propertyType=STRING )

Creating a constraint when there is an existing constraint with a different property type will fail

Example 40. CREATE CONSTRAINT

Create a node property type constraint restricting the property seriesOrder to float values on nodes with the Movie label, when a node property type constraint restricting the property seriesOrder to integer values already exists:

Query
CREATE CONSTRAINT order
FOR (movie:Movie) REQUIRE movie.seriesOrder IS :: FLOAT

In this case, the constraint cannot be created because there exists a conflicting constraint.

Error message
Constraint already exists: Constraint( id=23, name='seriesOrder', type='NODE PROPERTY TYPE', schema=(:Movie {seriesOrder}), propertyType=INTEGER )

Creating constraints on invalid types will fail

Example 41. CREATE CONSTRAINT

Create a node property type constraint restricting the property imdbScore to map values on nodes with the Movie label:

Query
CREATE CONSTRAINT score
FOR (movie:Movie) REQUIRE movie.imdbScore IS :: MAP

In this case, the constraint cannot be created because values of type MAP cannot be stored in properties and therefore are not permitted in property type constraints.

Error message
Failed to create node property type constraint: Invalid property type `MAP`.
Example 42. CREATE CONSTRAINT

Create a node property type constraint restricting the property imdbScore to list of nullable float values on nodes with the Movie label:

Query
CREATE CONSTRAINT score
FOR (movie:Movie) REQUIRE movie.imdbScore IS :: LIST<FLOAT>

In this case, the constraint cannot be created because the inner type of list types cannot be nullable. The correct type to use for the constraint is LIST<FLOAT NOT NULL> because null values cannot be stored as part of a list.

Error message
Failed to create node property type constraint: Invalid property type `LIST<FLOAT>`. Lists cannot have nullable inner types.
Example 43. CREATE CONSTRAINT

Create a node property type constraint restricting the property imdbScore to list of lists of float values on nodes with the Movie label:

Query
CREATE CONSTRAINT score
FOR (movie:Movie) REQUIRE movie.imdbScore IS :: LIST<LIST<FLOAT NOT NULL>>

In this case, the constraint cannot be created because the inner type of list types cannot be other lists.

Error message
Failed to create node property type constraint: Invalid property type `LIST<LIST<FLOAT NOT NULL>>`. Lists cannot have lists as an inner type.

Creating a node that complies with an existing constraint

Example 44. CREATE NODE

Create an Movie node with a STRING title property:

Query
CREATE (movie:Movie {title:'Iron Man'})
Result
Added 1 label, created 1 node, set 1 properties

Creating a node that violates an existing constraint will fail

Example 45. CREATE NODE

Create a Movie node with an integer title property, given a property type constraint on the label Movie restricting the title property to STRING values:

Query
CREATE (movie:Movie {title: 123})

In this case, the node is not created because the title property is in conflict with an existing constraint.

Error message
Node(0) with label `Movie` has property `title` of wrong type `Long`. Allowed types: STRING

Creating a constraint when there exist conflicting nodes will fail

Example 46. CREATE CONSTRAINT

Create a constraint restricting the property franchise to STRING values on nodes with the Movie label, when there already exists a node with a BOOLEAN franchise property:

Query
CREATE CONSTRAINT movie_franchise FOR (movie:Movie) REQUIRE movie.franchise IS :: STRING

In this case, the constraint cannot be created because it is in conflict with the existing graph. Remove or correct the offending nodes and then re-apply the constraint.

Error message
Unable to create Constraint( name='movie_franchise', type='NODE PROPERTY TYPE', schema=(:Movie {franchise}), propertyType=STRING ):
Node(0) with label `Movie` has property `franchise` of wrong type `Boolean`. Allowed types: STRING

The constraint creation fails on the first offending node that is found. This does not guarantee that there are no other offending nodes in the graph. Therefore, all the data should be checked and cleaned up before re-attempting the constraint creation.

This is an example MATCH query to find all offending nodes with the wrong property type for the constraint above:

Query
MATCH (movie:Movie)
WHERE movie.franchise IS NOT :: STRING
RETURN movie

Relationship property type constraints

This feature was introduced in Neo4j 5.9.

A relationship property type constraint ensures that certain relationships have a property of the required property type when the property exists on the relationhip.

The allowed property types for the constraints is:

  • BOOLEAN

  • STRING

  • INTEGER

  • FLOAT

  • DATE

  • LOCAL TIME

  • ZONED TIME

  • LOCAL DATETIME

  • ZONED DATETIME

  • DURATION

  • POINT

  • LIST<BOOLEAN NOT NULL> Introduced in 5.10

  • LIST<STRING NOT NULL> Introduced in 5.10

  • LIST<INTEGER NOT NULL> Introduced in 5.10

  • LIST<FLOAT NOT NULL> Introduced in 5.10

  • LIST<DATE NOT NULL> Introduced in 5.10

  • LIST<LOCAL TIME NOT NULL> Introduced in 5.10

  • LIST<ZONED TIME NOT NULL> Introduced in 5.10

  • LIST<LOCAL DATETIME NOT NULL> Introduced in 5.10

  • LIST<ZONED DATETIME NOT NULL> Introduced in 5.10

  • LIST<DURATION NOT NULL> Introduced in 5.10

  • LIST<POINT NOT NULL> Introduced in 5.10

  • Any closed dynamic union of the above types, e.g. INTEGER | FLOAT | STRING. Introduced in 5.11

For all available Cypher types, see the section on types and their synonyms.

Create a relationship property type constraint

When creating a relationship property type constraint, it is recommended to provide a constraint name.

Example 47. CREATE CONSTRAINT
Query
CREATE CONSTRAINT part_of
FOR ()-[part:PART_OF]-() REQUIRE part.order IS :: INTEGER
Result
Added 1 constraint.

Create a relationship property type constraint using a parameter

The constraint name can also be given as a parameter.

Example 48. CREATE CONSTRAINT
Parameters
{
  "name": "rel_prop_type_param"
}
Query
CREATE CONSTRAINT $name
FOR ()-[part:PART_OF]-() REQUIRE part.prop1 IS :: FLOAT
Result
Added 1 constraint.

Create a relationship property type constraint with a union type

This feature was introduced in Neo4j 5.11.

A closed dynamic union allows a relationship property to maintain some type flexibility whilst preventing unexpected values from being stored.

Example 49. CREATE CONSTRAINT
Query
CREATE CONSTRAINT part_of_tags
FOR ()-[part:PART_OF]-() REQUIRE part.tags IS :: STRING | LIST<STRING NOT NULL>
Result
Added 1 constraint.

Handling existing constraints when creating a constraint

Creating an already existing constraint will fail. To avoid such an error, IF NOT EXISTS can be added to the CREATE command. This will ensure that no error is thrown and that no constraint is created if any other constraint with the given name, or another relationship property type constraint on the same schema and property type, already exists. Introduced in 5.17 An informational notification is instead returned showing the existing constraint which blocks the creation.

Example 50. CREATE CONSTRAINT
Query
CREATE CONSTRAINT part_of IF NOT EXISTS
FOR ()-[part:PART_OF]-() REQUIRE part.order IS TYPED INTEGER

Assuming that such a constraint already exists:

Result
(no changes, no records)
Notification
`CREATE CONSTRAINT part_of IF NOT EXISTS FOR ()-[e:PART_OF]-() REQUIRE (e.order) IS :: INTEGER` has no effect.
`CONSTRAINT part_of FOR ()-[e:PART_OF]-() REQUIRE (e.order) IS :: INTEGER` already exists.

Creating an already existing constraint will fail

Example 51. CREATE CONSTRAINT

Create a relationship property type constraint restricting the property order to integer values on relationships with the PART_OF relationship type, when that constraint already exists:

Query
CREATE CONSTRAINT belongs_to
FOR ()-[part:PART_OF]-() REQUIRE part.order :: INTEGER

In this case, the constraint cannot be created because it already exists (but with a different name).

Error message
Constraint already exists: Constraint( id=24, name='part_of', type='RELATIONSHIP PROPERTY TYPE', schema=()-[:PART_OF {order}]-(), propertyType=INTEGER )

Creating a constraint when there is an existing constraint with a different property type will fail

Example 52. CREATE CONSTRAINT

Create a relationship property type constraint restricting the property order to float values on relationships with the PART_OF relationship type, when a relationship property type constraint restricting the property order to integer values already exists:

Query
CREATE CONSTRAINT order
FOR ()-[part:PART_OF]-() REQUIRE part.order IS :: FLOAT

In this case, the constraint cannot be created because there exists a conflicting constraint.

Error message
Constraint already exists: Constraint( id=24, name='part_of', type='RELATIONSHIP PROPERTY TYPE', schema=()-[:PART_OF {order}]-(), propertyType=INTEGER )

Creating constraints on invalid types will fail

Example 53. CREATE CONSTRAINT

Create a relationship property type constraint restricting the property releaseOrder to integer values excluding null on relationships with the PART_OF relationship type:

Query
CREATE CONSTRAINT score
FOR ()-[part:PART_OF]-() REQUIRE part.releaseOrder IS :: INTEGER NOT NULL

In this case, the constraint cannot be created because excluding null is not allowed in property type constraints. To also ensure that the property exists (is not null), add an existence constraint on the property.

Error message
Failed to create relationship property type constraint: Invalid property type `INTEGER NOT NULL`.
Example 54. CREATE CONSTRAINT

Create a relationship property type constraint restricting the property releaseOrder to list of nullable integer values on relationships with the PART_OF relationship type:

Query
CREATE CONSTRAINT score
FOR ()-[part:PART_OF]-() REQUIRE part.releaseOrder IS :: LIST<INTEGER>

In this case, the constraint cannot be created because the inner type of list types cannot be nullable. The correct type to use for the constraint is LIST<INTEGER NOT NULL> because null values cannot be stored as part of a list.

Error message
Failed to create relationship property type constraint: Invalid property type `LIST<INTEGER>`. Lists cannot have nullable inner types.
Example 55. CREATE CONSTRAINT

Create a relationship property type constraint restricting the property releaseOrder to list of lists of integer values on relationships with the PART_OF relationship type:

Query
CREATE CONSTRAINT score
FOR ()-[part:PART_OF]-() REQUIRE part.releaseOrder IS :: LIST<LIST<INTEGER NOT NULL>>

In this case, the constraint cannot be created because the inner type of list types cannot be other lists.

Error message
Failed to create relationship property type constraint: Invalid property type `LIST<LIST<INTEGER NOT NULL>>`. Lists cannot have lists as an inner type.

Creating a relationship that complies with an existing constraint

Example 56. CREATE RELATIONSHIP

Create a PART_OF relationship with an integer order property:

Query
MATCH (movie:Movie {title:'Iron Man'}), (franchise:Franchise {name:'MCU'})
CREATE (movie)-[part:PART_OF {order: 3}]->(franchise)
Result
Set 1 property, created 1 relationship

Creating a relationship that violates an existing constraint will fail

Example 57. CREATE RELATIONSHIP

Create a PART_OF relationship with a STRING order property, given a property type constraint on the relationship type PART_OF restricting the order property to integer values:

Query
MATCH (movie:Movie {title:'Captain America: The First Avenger'}), (franchise:Franchise {name:'MCU'})
CREATE (movie)-[part:PART_OF {order: '1'}]->(franchise)

In this case, the relationship is not created because the order property is in conflict with an existing constraint.

Error message
Relationship(0) with type `PART_OF` has property `order` of wrong type `String`. Allowed types: INTEGER

Creating a constraint when there exist conflicting relationships will fail

Example 58. CREATE CONSTRAINT

Create a constraint restricting the property releaseOrder to integer values on relationships with the PART_OF relationship type, when there already exists a relationship with a STRING releaseOrder property:

Query
CREATE CONSTRAINT release_order
FOR ()-[part:PART_OF]-() REQUIRE part.releaseOrder IS :: INTEGER

In this case, the constraint cannot be created because it is in conflict with the existing graph. Remove or correct the offending relationships and then re-apply the constraint.

Error message
Unable to create Constraint( name='release_order', type='RELATIONSHIP PROPERTY TYPE', schema=()-[:PART_OF {releaseOrder}]-(), propertyType=INTEGER ):
Relationship(0) with type `PART_OF` has property `releaseOrder` of wrong type `String`. Allowed types: INTEGER

The constraint creation fails on the first offending relationship that is found. This does not guarantee that there are no other offending relationships in the graph. Therefore, all the data should be checked and cleaned up before re-attempting the constraint creation.

This is an example MATCH query to find all offending relationships with the wrong property type for the constraint above:

Query
MATCH ()-[part:PART_OF]-()
WHERE part.releaseOrder IS NOT :: INTEGER
RETURN part

Node key constraints

A node key constraint ensures that certain nodes have a set of specified properties whose combined value is unique and all properties in the set are present.

Create a node key constraint

When creating a node key constraint, it is recommended to provide a constraint name.

Example 59. CREATE CONSTRAINT
Query
CREATE CONSTRAINT actor_fullname
FOR (actor:Actor) REQUIRE (actor.firstname, actor.surname) IS NODE KEY
Result
Added 1 constraint.

Create a node key constraint using a parameter

The constraint name can also be given as a parameter.

Example 60. CREATE CONSTRAINT
Parameters
{
  "name": "node_key_param"
}
Query
CREATE CONSTRAINT $name
FOR (actor:Actor) REQUIRE actor.firstname IS KEY
Result
Added 1 constraint.

Handling existing constraints when creating a constraint

Creating an already existing constraint will fail. To avoid such an error, IF NOT EXISTS can be added to the CREATE command. This will ensure that no error is thrown and that no constraint is created if any other constraint with the given name, or another node key constraint on the same schema, already exists. Introduced in 5.17 An informational notification is instead returned showing the existing constraint which blocks the creation.

Example 61. CREATE CONSTRAINT
Query
CREATE CONSTRAINT actor_names IF NOT EXISTS
FOR (actor:Actor) REQUIRE (actor.firstname, actor.surname) IS NODE KEY

Assuming a node key constraint on (:Actor {firstname, surname}) already exists:

Result
(no changes, no records)
Notification
`CREATE CONSTRAINT actor_names IF NOT EXISTS FOR (e:Actor) REQUIRE (e.firstname, e.surname) IS NODE KEY` has no effect.
`CONSTRAINT actor_fullname FOR (e:Actor) REQUIRE (e.firstname, e.surname) IS NODE KEY` already exists.

Specifying an index provider when creating a constraint

To create a node key constraint with a specific index provider for the backing index, the OPTIONS clause is used.

The index type of the backing index is set with the indexProvider option.

The only valid value for the index provider is:

  • range-1.0 Default

Example 62. CREATE CONSTRAINT
Query
CREATE CONSTRAINT constraint_with_provider
FOR (actor:Actor) REQUIRE (actor.surname) IS NODE KEY
OPTIONS {
  indexProvider: 'range-1.0'
}
Result
Added 1 constraint.

There is no valid index configuration values for the constraint-backing range indexes.

Node key and property uniqueness constraints are not allowed on the same schema

Example 63. CREATE CONSTRAINT

Create a node key constraint on the properties firstname and age on nodes with the Actor label, when a property uniqueness constraint already exists on the same label and property combination:

Query
CREATE CONSTRAINT actor_name_age FOR (actor:Actor) REQUIRE (actor.firstname, actor.age) IS NODE KEY

In this case, the constraint cannot be created because there already exist a conflicting constraint on that label and property combination.

Error message
Constraint already exists:
Constraint( id=10, name='preExisting_actor_name_age', type='UNIQUENESS', schema=(:Actor {firstname, age}), ownedIndex=9 )

Creating a constraint on same name as an existing index will fail

Example 64. CREATE CONSTRAINT

Create a named node key constraint on the property citizenship on nodes with the Actor label, when an index already exists with the given name:

Query
CREATE CONSTRAINT citizenship
FOR (actor:Actor) REQUIRE actor.citizenship IS NODE KEY

In this case, the constraint cannot be created because there already exists an index with the given name.

Error message
There already exists an index called 'citizenship'.

Creating a node that complies with an existing constraint

Example 65. CREATE NODE

Create an Actor node with firstname and surname properties:

Query
CREATE (actor:Actor {firstname: 'Keanu', surname: 'Reeves'})
Result
Added 1 label, created 1 node, set 2 properties.

Creating a node that violates an existing constraint will fail

Example 66. CREATE NODE

Create an Actor node without a firstname property, given a node key constraint on :Actor(firstname, surname):

Query
CREATE (actor:Actor {surname: 'Wood'})

In this case, the node is not created because it is missing the firstname property which is in conflict with an existing constraint.

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

Removing a NODE KEY-constrained property will fail

Example 67. REMOVE PROPERTY

Remove the firstname property from an existing node Actor, given a NODE KEY constraint on :Actor(firstname, surname):

Query
MATCH (actor:Actor {firstname: 'Keanu', surname: 'Reeves'}) REMOVE actor.firstname

In this case, the property is not removed because it is in conflict with an existing constraint.

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

Creating a constraint when there exist conflicting node will fail

Example 68. CREATE CONSTRAINT

Create a node key constraint on the property born on nodes with the Actor label, when a node without a born property already exists in the graph:

Query
CREATE CONSTRAINT actor_born FOR (actor:Actor) REQUIRE (actor.born) IS NODE KEY

In this case, the node key constraint cannot be created because it is in conflict with the existing graph. Either use Create, show, and delete indexes instead, or remove/correct the offending nodes and then re-apply the constraint.

Error message
Unable to create Constraint( type='NODE KEY', schema=(:Actor {born}) ):
Node(0) with label `Actor` must have the property `born`

The constraint creation fails on the first offending nodes that are found. This does not guarantee that there are no other offending nodes in the graph. Therefore, all the data should be checked and cleaned up before re-attempting the constraint creation.

This is an example MATCH query to find all offending nodes for the constraint above:

Query
MATCH (actor1:Actor), (actor2:Actor)
WHERE actor1.born = actor2.born AND NOT actor1 = actor2
UNWIND [actor1, actor2] AS actor
RETURN actor, 'non-unique' AS reason

UNION

MATCH (actor:Actor)
WHERE actor.born IS NULL
RETURN actor, 'non-existing' AS reason

Relationship key constraints

This feature was introduced in Neo4j 5.7.

A relationship key constraint ensures that certain relationships have a set of defined properties whose combined value is unique. It also ensures that all properties in the set are present.

Create a relationship key constraint

When creating a relationship key constraint, it is recommended to provide a constraint name.

Example 69. CREATE CONSTRAINT
Query
CREATE CONSTRAINT knows_since_how
FOR ()-[knows:KNOWS]-() REQUIRE (knows.since, knows.how) IS RELATIONSHIP KEY
Result
Added 1 constraint.

Create a relationship key constraint using a parameter

The constraint name can also be given as a parameter.

Example 70. CREATE CONSTRAINT
Parameters
{
  "name": "rel_key_param"
}
Query
CREATE CONSTRAINT $name
FOR ()-[knows:KNOWS]-() REQUIRE knows.friend IS KEY
Result
Added 1 constraint.

Handling existing constraints when creating a constraint

Creating an already existing constraint will fail. To avoid such an error, IF NOT EXISTS can be added to the CREATE command. This will ensure that no error is thrown and that no constraint is created if any other constraint with the given name, or another relationship key constraint on the same schema, already exists. Introduced in 5.17 An informational notification is instead returned showing the existing constraint which blocks the creation.

Example 71. CREATE CONSTRAINT
Query
CREATE CONSTRAINT knows IF NOT EXISTS
FOR ()-[knows:KNOWS]-() REQUIRE (knows.since, knows.how) IS RELATIONSHIP KEY

Assuming a relationship key constraint on ()-[:KNOWS {since, how}]-() already exists:

Result
(no changes, no records)
Notification
`CREATE CONSTRAINT knows IF NOT EXISTS FOR ()-[e:KNOWS]-() REQUIRE (e.since, e.how) IS RELATIONSHIP KEY` has no effect.
`CONSTRAINT knows_since_how FOR ()-[e:KNOWS]-() REQUIRE (e.since, e.how) IS RELATIONSHIP KEY` already exists.

Specifying an index provider when creating a constraint

To create a relationship key constraint with a specific index provider for the backing index, the OPTIONS clause is used.

The index type of the backing index is set with the indexProvider option.

The only valid value for the index provider is:

  • range-1.0 Default

Example 72. CREATE CONSTRAINT
Query
CREATE CONSTRAINT rel_constraint_with_provider
FOR ()-[knows:KNOWS]-() REQUIRE (knows.since) IS REL KEY
OPTIONS {
  indexProvider: 'range-1.0'
}
Result
Added 1 constraint.

There is no valid index configuration values for the constraint-backing range indexes.

Relationship key and property uniqueness constraints are not allowed on the same schema

Example 73. CREATE CONSTRAINT

Create a relationship key constraint on the property how on relationships with the KNOWS relationship type, when a property uniqueness constraint already exists on the same relationship type and property combination:

Query
CREATE CONSTRAINT knows_how FOR ()-[knows:KNOWS]-() REQUIRE (knows.how) IS REL KEY

In this case, the constraint cannot be created because there already exists a conflicting constraint on that relationship type and property combination.

Error message
Constraint already exists:
Constraint( id=34, name='preExisting_how', type='RELATIONSHIP UNIQUENESS', schema=()-[:KNOWS {how}]-(), ownedIndex=33 )

The constraint type for relationship property uniqueness constraints will be updated to say RELATIONSHIP PROPERTY UNIQUENESS in Neo4j 6.0.

Creating a constraint on same name as an existing index will fail

Example 74. CREATE CONSTRAINT

Create a named relationship key constraint on the property level on relationships with the KNOWS relationship type, when an index already exists with the given name:

Query
CREATE CONSTRAINT knows
FOR ()-[knows:KNOWS]-() REQUIRE (knows.level) IS REL KEY

In this case, the constraint cannot be created because there already exists an index with the given name.

Error message
There already exists an index called 'knows'.

Creating a relationship that complies with an existing constraint

Example 75. CREATE RELATIONSHIP

Create a KNOWS relationship with both since and how properties and a relationship key constraint on :KNOWS(since, how):

Query
CREATE (:Actor {firstname: 'Jensen', surname: 'Ackles'})-[:KNOWS {since: 2008, how: 'coworkers', friend: true}]->(:Actor {firstname: 'Misha', surname: 'Collins'})
Result
Added 2 labels, created 2 nodes, set 6 properties, created 1 relationship.

Creating a relationship that violates an existing constraint will fail

Example 76. CREATE RELATIONSHIP

Create a KNOWS relationship without a since property, given a relationship key constraint on :KNOWS(since, how):

Query
MATCH (jensen:Actor {firstname: 'Jensen', surname: 'Ackles'}), (misha:Actor {firstname: 'Misha', surname: 'Collins'})
CREATE (misha)-[:KNOWS {how: 'coworkers'}]->(jensen)

In this case, the relationship is not created because it is missing the since property which is in conflict with an existing constraint.

Error message
Relationship(0) already exists with type `KNOWS` and property `how` = 'coworkers'

Removing a RELATIONSHIP KEY-constrained property will fail

Example 77. REMOVE PROPERTY

Remove the since property from an existing relationship KNOWS, given a RELATIONSHIP KEY constraint on :KNOWS(since, how):

Query
MATCH ()-[knows:KNOWS {since: 2008, how: 'coworkers'}]->() REMOVE knows.since

In this case, the property is not removed because it is in conflict with an existing constraint.

Error message
Relationship(0) with type `KNOWS` must have the properties (`since`, `how`)

Creating a constraint when there exist conflicting relationships will fail

Example 78. CREATE CONSTRAINT

Create a relationship key constraint on the property level on relationships with the KNOWS relationship type, when two relationships with identical level property values already exist in the graph:

Query
CREATE CONSTRAINT knows_level FOR ()-[knows:KNOWS]-() REQUIRE (knows.level) IS REL KEY

In this case, the relationship key constraint cannot be created because it is in conflict with the existing graph. Either use Create, show, and delete indexes instead, or remove or correct the offending relationships and then re-apply the constraint.

Error message
Unable to create Constraint( name='knows_level', type='RELATIONSHIP KEY', schema=()-[:KNOWS {level}]-() ):
Both Relationship(0) and Relationship(1) have the type `KNOWS` and property `level` = 10

The constraint creation fails on the first offending relationships that are found. This does not guarantee that there are no other offending relationships in the graph. Therefore, all the data should be checked and cleaned up before re-attempting the constraint creation.

This is an example MATCH query to find all offending relationships for the constraint above:

Query
MATCH ()-[knows1:KNOWS]->(), ()-[knows2:KNOWS]->()
WHERE knows1.level = knows2.level AND NOT knows1 = knows2
UNWIND [knows1, knows2] AS knows
RETURN knows, 'non-unique' AS reason
UNION
MATCH ()-[knows:KNOWS]->()
WHERE knows.level IS NULL
RETURN knows, 'non-existing' AS reason

Drop a constraint by name

A constraint can be dropped using the name with the DROP CONSTRAINT constraint_name command. It is the same command for all constraint types. The name of the constraint can be found using the SHOW CONSTRAINTS command, given in the output column name.

Drop a constraint

A constraint can be dropped using the name with the DROP CONSTRAINT command.

Example 79. DROP CONSTRAINT
Query
DROP CONSTRAINT book_isbn
Result
Removed 1 constraint.

Drop a constraint using a parameter

The constraint name can also be given as a parameter.

Example 80. DROP CONSTRAINT
Parameters
{
  "name": "node_uniqueness_param"
}
Query
DROP CONSTRAINT $name
Result
Removed 1 constraint.

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.

Example 81. DROP CONSTRAINT
Query
DROP CONSTRAINT missing_constraint_name IF EXISTS
Result
(no changes, no records)
Notification
`DROP CONSTRAINT missing_constraint_name IF EXISTS` has no effect. `missing_constraint_name` does not exist.

Listing constraints

Listing all constraints

To list all constraints with the default output columns, the SHOW CONSTRAINTS command can be used. If all columns are required, use SHOW CONSTRAINTS YIELD *.

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.

Example 82. SHOW CONSTRAINTS
Query
SHOW CONSTRAINTS
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id | name                           | type                              | entityType     | labelsOrTypes | properties                         | ownedIndex                     | propertyType                     |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 36 | "actor_fullname"               | "NODE_KEY"                        | "NODE"         | ["Actor"]     | ["firstname", "surname"]           | "actor_fullname"               | null                             |
| 21 | "author_name"                  | "NODE_PROPERTY_EXISTENCE"         | "NODE"         | ["Author"]    | ["name"]                           | null                           | null                             |
| 24 | "author_pseudonym"             | "UNIQUENESS"                      | "NODE"         | ["Author"]    | ["pseudonym"]                      | "author_pseudonym"             | null                             |
| 8  | "book_isbn2"                   | "UNIQUENESS"                      | "NODE"         | ["Book"]      | ["isbn2"]                          | "book_isbn2"                   | null                             |
| 10 | "constraint_with_options"      | "UNIQUENESS"                      | "NODE"         | ["Book"]      | ["prop1", "prop2"]                 | "constraint_with_options"      | null                             |
| 40 | "constraint_with_provider"     | "NODE_KEY"                        | "NODE"         | ["Actor"]     | ["surname"]                        | "constraint_with_provider"     | null                             |
| 45 | "knows_since_how"              | "RELATIONSHIP_KEY"                | "RELATIONSHIP" | ["KNOWS"]     | ["since", "how"]                   | "knows_since_how"              | null                             |
| 30 | "movie_tagline"                | "NODE_PROPERTY_TYPE"              | "NODE"         | ["Movie"]     | ["tagline"]                        | null                           | "STRING | LIST<STRING NOT NULL>" |
| 28 | "movie_title"                  | "NODE_PROPERTY_TYPE"              | "NODE"         | ["Movie"]     | ["title"]                          | null                           | "STRING"                         |
| 22 | "node_exist_param"             | "NODE_PROPERTY_EXISTENCE"         | "NODE"         | ["Author"]    | ["surname"]                        | null                           | null                             |
| 38 | "node_key_param"               | "NODE_KEY"                        | "NODE"         | ["Actor"]     | ["firstname"]                      | "node_key_param"               | null                             |
| 29 | "node_prop_type_param"         | "NODE_PROPERTY_TYPE"              | "NODE"         | ["Movie"]     | ["prop1"]                          | null                           | "INTEGER"                        |
| 32 | "part_of"                      | "RELATIONSHIP_PROPERTY_TYPE"      | "RELATIONSHIP" | ["PART_OF"]   | ["order"]                          | null                           | "INTEGER"                        |
| 34 | "part_of_tags"                 | "RELATIONSHIP_PROPERTY_TYPE"      | "RELATIONSHIP" | ["PART_OF"]   | ["tags"]                           | null                           | "STRING | LIST<STRING NOT NULL>" |
| 42 | "preExisting_actor_name_age"   | "UNIQUENESS"                      | "NODE"         | ["Actor"]     | ["firstname", "age"]               | "preExisting_actor_name_age"   | null                             |
| 12 | "preExisting_book_published"   | "UNIQUENESS"                      | "NODE"         | ["Book"]      | ["published"]                      | "preExisting_book_published"   | null                             |
| 51 | "preExisting_how"              | "RELATIONSHIP_UNIQUENESS"         | "RELATIONSHIP" | ["KNOWS"]     | ["how"]                            | "preExisting_how"              | null                             |
| 19 | "rel_constraint_with_options"  | "RELATIONSHIP_UNIQUENESS"         | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order", "seriesTitle", "number"] | "rel_constraint_with_options"  | null                             |
| 49 | "rel_constraint_with_provider" | "RELATIONSHIP_KEY"                | "RELATIONSHIP" | ["KNOWS"]     | ["since"]                          | "rel_constraint_with_provider" | null                             |
| 26 | "rel_exist_param"              | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"]     | ["published"]                      | null                           | null                             |
| 47 | "rel_key_param"                | "RELATIONSHIP_KEY"                | "RELATIONSHIP" | ["KNOWS"]     | ["friend"]                         | "rel_key_param"                | null                             |
| 33 | "rel_prop_type_param"          | "RELATIONSHIP_PROPERTY_TYPE"      | "RELATIONSHIP" | ["PART_OF"]   | ["prop1"]                          | null                           | "FLOAT"                          |
| 17 | "rel_uniqueness_param"         | "RELATIONSHIP_UNIQUENESS"         | "RELATIONSHIP" | ["SEQUEL_OF"] | ["prop1"]                          | "rel_uniqueness_param"         | null                             |
| 15 | "sequels"                      | "RELATIONSHIP_UNIQUENESS"         | "RELATIONSHIP" | ["SEQUEL_OF"] | ["order", "seriesTitle"]           | "sequels"                      | null                             |
| 31 | "seriesOrder"                  | "NODE_PROPERTY_TYPE"              | "NODE"         | ["Movie"]     | ["seriesOrder"]                    | null                           | "INTEGER"                        |
| 27 | "wrote_locations"              | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"]     | ["location"]                       | null                           | null                             |
| 25 | "wrote_year"                   | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"]     | ["year"]                           | null                           | null                             |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
27 rows

The type column returns UNIQUENESS for the node property uniqueness constraint and RELATIONSHIP_UNIQUENESS for the relationship property uniqueness constraint. This will be updated in Neo4j 6.0. Node property uniqueness constraints will be updated to NODE_PROPERTY_UNIQUENESS and relationship property uniqueness constraints to RELATIONSHIP_PROPERTY_UNIQUENESS.

Listing constraints with filtering

One way of filtering the output from SHOW CONSTRAINTS by constraint type is the use of constraint type keywords, listed in the syntax for listing constraints type filter table. For example, to show only property uniqueness constraints, use SHOW UNIQUENESS CONSTRAINTS. Another more flexible way of filtering the output is to use the WHERE clause. An example is to only show constraints on relationships.

Example 83. SHOW CONSTRAINTS
Query
SHOW EXISTENCE CONSTRAINTS
WHERE entityType = 'RELATIONSHIP'

This will only return the default output columns. To get all columns, use SHOW INDEXES YIELD * WHERE ....

+-----------------------------------------------------------------------------------------------------------------------------------------+
| id | name              | type                              | entityType     | labelsOrTypes | properties    | ownedIndex | propertyType |
+-----------------------------------------------------------------------------------------------------------------------------------------+
| 26 | "rel_exist_param" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"]     | ["published"] | null       | null         |
| 27 | "wrote_locations" | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"]     | ["location"]  | null       | null         |
| 25 | "wrote_year"      | "RELATIONSHIP_PROPERTY_EXISTENCE" | "RELATIONSHIP" | ["WROTE"]     | ["year"]      | null       | null         |
+-----------------------------------------------------------------------------------------------------------------------------------------+
3 rows