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.
CREATE CONSTRAINT book_isbn
FOR (book:Book) REQUIRE book.isbn IS UNIQUE
Added 1 constraint.
The detailed statistics view currently says |
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.
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:
Added 1 constraint.
The detailed statistics view currently says |
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
CREATE CONSTRAINT constraint_with_options
FOR (book:Book) REQUIRE (book.prop1, book.prop2) IS UNIQUE
OPTIONS {
indexProvider: 'range-1.0'
}
Added 1 constraint.
The detailed statistics view currently says |
There is no valid index configuration values for the constraint-backing range indexes.
Creating an already existing constraint will fail
Create a property uniqueness constraint on the property published
on nodes with the Book
label, when that constraint already exists:
CREATE CONSTRAINT book_published FOR (book:Book) REQUIRE book.published IS UNIQUE
In this case, the constraint cannot be created because it already exists.
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 |
Creating a constraint on the same schema as an existing index will fail
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:
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.
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
Create a Book
node with an isbn
that is not already in the graph:
CREATE (book:Book {isbn: '1449356265', title: 'Graph Databases'})
Added 1 label, created 1 node, set 2 properties
Creating a node that violates an existing constraint will fail
Create a Book
node with an isbn
that is already used in the graph:
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.
Node(0) already exists with label `Book` and property `isbn` = '1449356265'
Creating a constraint when there exist conflicting nodes will fail
Create a property uniqueness constraint on the property title
on nodes with the Book
label, when there are two nodes with the same title
:
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 Indexes for search performance instead, or remove/correct the offending nodes and then re-apply the constraint.
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 |
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:
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.
CREATE CONSTRAINT sequels
FOR ()-[sequel:SEQUEL_OF]-() REQUIRE (sequel.order, sequel.seriesTitle) IS UNIQUE
Added 1 constraint.
The detailed statistics view currently says |
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.
CREATE CONSTRAINT sequels IF NOT EXISTS
FOR ()-[sequel:SEQUEL_OF]-() REQUIRE (sequel.order) IS UNIQUE
Assuming a constraint with the name sequels
already exists:
(no changes, no records)
The detailed statistics view currently says |
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
CREATE CONSTRAINT rel_constraint_with_options
FOR ()-[sequel:SEQUEL_OF]-() REQUIRE (sequel.order, sequel.seriesTitle, sequel.number) IS UNIQUE
OPTIONS {
indexProvider: 'range-1.0'
}
Added 1 constraint.
The detailed statistics view currently says |
There are no valid index configuration values for the constraint-backing range indexes.
Creating an already existing constraint will fail
Create a property uniqueness constraint on the properties order
and seriesTitle
on relationships with the SEQUEL_OF
relationship type, when that constraint already exists:
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.
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 |
Creating a constraint on the same schema as an existing index will fail
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:
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.
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
Create a SEQUEL_OF
relationship with values for properties order
and seriesTitle
that are not already in the graph:
CREATE (:Book {title: 'Spirit Walker'})-[:SEQUEL_OF {order: 1, seriesTitle: 'Chronicles of Ancient Darkness'}]->(:Book {title: 'Wolf Brother'})
Added 2 labels, created 2 nodes, set 4 properties, created 1 relationship.
Creating a relationship that violates an existing constraint will fail
Create a SEQUEL_OF
relationship with values for properties order
and seriesTitle
that are already used in the graph:
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.
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
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:
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 Indexes for search performance instead, or remove/correct the offending relationships and then re-apply the constraint.
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:
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.
CREATE CONSTRAINT author_name
FOR (author:Author) REQUIRE author.name IS NOT NULL
Added 1 constraint.
The detailed statistics view for property existence constraints, |
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.
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:
(no changes, no records)
Creating an already existing constraint will fail
Create a node property existence constraint on the property name
on nodes with the Author
label, when that constraint already exists:
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.
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
Create an Author
node with a name
property:
CREATE (author:Author {name:'Virginia Woolf'})
Added 1 label, created 1 node, set 1 properties
Creating a node that violates an existing constraint will fail
Create an Author
node without a name
property, given a property existence constraint on :Author(name)
:
CREATE (author:Author)
In this case, the node is not created because it is missing the name
property which is in conflict with an existing constraint.
Node(0) with label `Author` must have the property `name`
Removing an existence constrained node property will fail
Remove the name
property from an existing node Author
, given a property existence constraint on :Author(name)
:
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.
Node(0) with label `Author` must have the property `name`
Creating a constraint when there exist conflicting nodes will fail
Create a constraint on the property nationality
on nodes with the Author
label, when there already exists a node without a nationality
property:
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.
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:
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.
CREATE CONSTRAINT wrote_year
FOR ()-[wrote:WROTE]-() REQUIRE wrote.year IS NOT NULL
Added 1 constraint.
The detailed statistics view for property existence constraints, |
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.
CREATE CONSTRAINT wrote_year IF NOT EXISTS
FOR ()-[wrote:WROTE]-() REQUIRE wrote.year IS NOT NULL
Assuming that such a constraint already exists:
(no changes, no records)
Creating an already existing constraint will fail
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:
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.
There already exists a constraint called 'wrote_locations'.
Creating a relationship that complies with an existing constraint
Create a WROTE
relationship with a year
and location
property, given property existence constraints on :WROTE(year)
and :WROTE(location)
:
CREATE (author:Author {name: 'Emily Brontë'})-[wrote:WROTE {year: 1847, location: 'Haworth, United Kingdom'}]->(book:Book {title:'Wuthering Heights', isbn: 9789186579296})
Added 2 labels, created 2 nodes, set 5 properties, created 1 relationship
Creating a relationship that violates an existing constraint will fail
Create a WROTE
relationship without a location
property, given a property existence constraint :WROTE(location)
:
CREATE (author:Author {name: 'Charlotte Brontë'})-[wrote:WROTE {year: 1847}]->(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.
Relationship(0) with type `WROTE` must have the property `location`
Removing an existence constrained relationship property will fail
Remove the location
property from an existing relationship of relationship type WROTE
, given a property existence constraint :WROTE(location)
:
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.
Relationship(0) with type `WROTE` must have the property `location`
Creating a constraint when there exist conflicting relationships will fail
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
:
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.
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:
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.
CREATE CONSTRAINT movie_title
FOR (movie:Movie) REQUIRE movie.title IS :: STRING
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.
CREATE CONSTRAINT movie_tagline
FOR (movie:Movie) REQUIRE movie.tagline IS :: STRING | LIST<STRING NOT NULL>
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.
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:
(no changes, no records)
Creating an already existing constraint will fail
Create a node property type constraint restricting the property title
to string values on nodes with the Movie
label, when that constraint already exists:
CREATE CONSTRAINT movies
FOR (movie:Movie) REQUIRE movie.title IS TYPED STRING
In this case, the constraint cannot be created because it already exists.
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
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:
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.
Constraint already exists: Constraint( id=23, name='seriesOrder', type='NODE PROPERTY TYPE', schema=(:Movie {seriesOrder}), propertyType=INTEGER )
Creating constraints on invalid types will fail
Create a node property type constraint restricting the property imdbScore
to map values on nodes with the Movie
label:
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.
Failed to create node property type constraint: Invalid property type `MAP`.
Create a node property type constraint restricting the property imdbScore
to list of nullable float values on nodes with the Movie
label:
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.
Failed to create node property type constraint: Invalid property type `LIST<FLOAT>`. Lists cannot have nullable inner types.
Create a node property type constraint restricting the property imdbScore
to list of lists of float values on nodes with the Movie
label:
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.
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
Create an Movie
node with a string title
property:
CREATE (movie:Movie {title:'Iron Man'})
Added 1 label, created 1 node, set 1 properties
Creating a node that violates an existing constraint will fail
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:
CREATE (movie:Movie {title: 123})
In this case, the node is not created because the title
property is in conflict with an existing constraint.
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
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:
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.
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:
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.
-
Creating a constraint when there is an existing constraint with a different property type will fail
-
Creating a relationship that complies with an existing constraint
-
Creating a relationship that violates an existing constraint will fail
-
Creating a constraint when there exist conflicting relationships will fail
Create a relationship property type constraint
When creating a relationship property type constraint, it is recommended to provide a constraint name.
CREATE CONSTRAINT part_of
FOR ()-[part:PART_OF]-() REQUIRE part.order IS :: INTEGER
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.
CREATE CONSTRAINT part_of_tags
FOR ()-[part:PART_OF]-() REQUIRE part.tags IS :: STRING | LIST<STRING NOT NULL>
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.
CREATE CONSTRAINT part_of IF NOT EXISTS
FOR ()-[part:PART_OF]-() REQUIRE part.order IS TYPED INTEGER
Assuming that such a constraint already exists:
(no changes, no records)
Creating an already existing constraint will fail
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:
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).
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
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:
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.
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
Create a relationship property type constraint restricting the property releaseOrder
to integer values excluding null
on relationships with the PART_OF
relationship type:
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.
Failed to create relationship property type constraint: Invalid property type `INTEGER NOT NULL`.
Create a relationship property type constraint restricting the property releaseOrder
to list of nullable integer values on relationships with the PART_OF
relationship type:
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.
Failed to create relationship property type constraint: Invalid property type `LIST<INTEGER>`. Lists cannot have nullable inner types.
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:
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.
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
Create a PART_OF
relationship with an integer order
property:
MATCH (movie:Movie {title:'Iron Man'}), (franchise:Franchise {name:'MCU'})
CREATE (movie)-[part:PART_OF {order: 3}]->(franchise)
Set 1 property, created 1 relationship
Creating a relationship that violates an existing constraint will fail
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:
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.
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
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:
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.
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:
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.
CREATE CONSTRAINT actor_fullname
FOR (actor:Actor) REQUIRE (actor.firstname, actor.surname) IS NODE KEY
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.
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:
(no changes, no records)
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
CREATE CONSTRAINT constraint_with_provider
FOR (actor:Actor) REQUIRE (actor.surname) IS NODE KEY
OPTIONS {
indexProvider: 'range-1.0'
}
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
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:
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.
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
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:
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.
There already exists an index called 'citizenship'.
Creating a node that complies with an existing constraint
Create an Actor
node with firstname
and surname
properties:
CREATE (actor:Actor {firstname: 'Keanu', surname: 'Reeves'})
Added 1 label, created 1 node, set 2 properties.
Creating a node that violates an existing constraint will fail
Create an Actor
node without a firstname
property, given a node key constraint on :Actor(firstname, surname)
:
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.
Node(0) with label `Actor` must have the properties (`firstname`, `surname`)
Removing a NODE KEY-constrained property will fail
Remove the firstname
property from an existing node Actor
, given a NODE KEY
constraint on :Actor(firstname, surname)
:
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.
Node(0) with label `Actor` must have the properties (`firstname`, `surname`)
Creating a constraint when there exist conflicting node will fail
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:
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 Indexes for search performance instead, or remove/correct the offending nodes and then re-apply the constraint.
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:
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.
-
Relationship key and property uniqueness constraints are not allowed on the same schema
-
Creating a constraint on same name as an existing index will fail
-
Creating a relationship that complies with an existing constraint
-
Creating a relationship that violates an existing constraint will fail
-
Creating a constraint when there exist conflicting relationships will fail
Create a relationship key constraint
When creating a relationship key constraint, it is recommended to provide a constraint name.
CREATE CONSTRAINT knows_since_how
FOR ()-[knows:KNOWS]-() REQUIRE (knows.since, knows.how) IS RELATIONSHIP KEY
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.
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:
(no changes, no records)
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
CREATE CONSTRAINT rel_constraint_with_provider
FOR ()-[knows:KNOWS]-() REQUIRE (knows.since) IS REL KEY
OPTIONS {
indexProvider: 'range-1.0'
}
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
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:
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.
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 |
Creating a constraint on same name as an existing index will fail
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:
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.
There already exists an index called 'knows'.
Creating a relationship that complies with an existing constraint
Create a KNOWS
relationship with both since
and how
properties and a relationship key constraint on :KNOWS(since, how)
:
CREATE (:Actor {firstname: 'Jensen', surname: 'Ackles'})-[:KNOWS {since: 2008, how: 'coworkers'}]->(:Actor {firstname: 'Misha', surname: 'Collins'})
Added 2 labels, created 2 nodes, set 6 properties, created 1 relationship.
Creating a relationship that violates an existing constraint will fail
Create a KNOWS
relationship without a since
property, given a relationship key constraint on :KNOWS(since, how)
:
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.
Relationship(0) already exists with type `KNOWS` and property `how` = 'coworkers'
Removing a RELATIONSHIP KEY-constrained property will fail
Remove the since
property from an existing relationship KNOWS
, given a RELATIONSHIP KEY
constraint on :KNOWS(since, how)
:
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.
Relationship(0) with type `KNOWS` must have the properties (`since`, `how`)
Creating a constraint when there exist conflicting relationships will fail
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:
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 Indexes for search performance instead, or remove or correct the offending relationships and then re-apply the constraint.
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:
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
Drop a constraint
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 CONSTRAINT book_isbn
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
.
It is the same command for all constraint types.
DROP CONSTRAINT missing_constraint_name IF EXISTS
(no changes, no records)
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
╒════╤══════════════════════════════╤═════════════════════════════════╤══════════════╤═══════════════╤════════════════════════════════╤═══════════════════════════════╤═════════════════════════════════╕ │"id"│"name" │"type" │"entityType" │"labelsOrTypes"│"properties" │"ownedIndex" │"propertyType" │ ╞════╪══════════════════════════════╪═════════════════════════════════╪══════════════╪═══════════════╪════════════════════════════════╪═══════════════════════════════╪═════════════════════════════════╡ │26 │"actor_fullname" │"NODE_KEY" │"NODE" │["Actor"] │["firstname","surname"] │"actor_fullname" │null │ ├────┼──────────────────────────────┼─────────────────────────────────┼──────────────┼───────────────┼────────────────────────────────┼───────────────────────────────┼─────────────────────────────────┤ │17 │"author_name" │"NODE_PROPERTY_EXISTENCE" │"NODE" │["Author"] │["name"] │null │null │ ├────┼──────────────────────────────┼─────────────────────────────────┼──────────────┼───────────────┼────────────────────────────────┼───────────────────────────────┼─────────────────────────────────┤ │19 │"author_pseudonym" │"UNIQUENESS" │"NODE" │["Author"] │["pseudonym"] │"author_pseudonym" │null │ ├────┼──────────────────────────────┼─────────────────────────────────┼──────────────┼───────────────┼────────────────────────────────┼───────────────────────────────┼─────────────────────────────────┤ │6 │"book_isbn2" │"UNIQUENESS" │"NODE" │["Book"] │["isbn2"] │"book_isbn2" │null │ ├────┼──────────────────────────────┼─────────────────────────────────┼──────────────┼───────────────┼────────────────────────────────┼───────────────────────────────┼─────────────────────────────────┤ │8 │"constraint_with_options" │"UNIQUENESS" │"NODE" │["Book"] │["prop1","prop2"] │"constraint_with_options" │null │ ├────┼──────────────────────────────┼─────────────────────────────────┼──────────────┼───────────────┼────────────────────────────────┼───────────────────────────────┼─────────────────────────────────┤ │28 │"constraint_with_provider" │"NODE_KEY" │"NODE" │["Actor"] │["surname"] │"constraint_with_provider" │null │ ├────┼──────────────────────────────┼─────────────────────────────────┼──────────────┼───────────────┼────────────────────────────────┼───────────────────────────────┼─────────────────────────────────┤ │33 │"knows_since_how" │"RELATIONSHIP_KEY" │"RELATIONSHIP"│["KNOWS"] │["since","how"] │"knows_since_how" │null │ ├────┼──────────────────────────────┼─────────────────────────────────┼──────────────┼───────────────┼────────────────────────────────┼───────────────────────────────┼─────────────────────────────────┤ │22 │"movie_title" │"NODE_PROPERTY_TYPE" │"NODE" │["Movie"] │["title"] │null │"STRING" │ ├────┼──────────────────────────────┼─────────────────────────────────┼──────────────┼───────────────┼────────────────────────────────┼───────────────────────────────┼─────────────────────────────────┤ │24 │"part_of" │"RELATIONSHIP_PROPERTY_TYPE" │"RELATIONSHIP"│["PART_OF"] │["order"] │null │"INTEGER" │ ├────┼──────────────────────────────┼─────────────────────────────────┼──────────────┼───────────────┼────────────────────────────────┼───────────────────────────────┼─────────────────────────────────┤ │39 │"part_of_tags" │"RELATIONSHIP_PROPERTY_TYPE" │"RELATIONSHIP"│["PART_OF"] │["tags "] │null │"STRING | LIST<STRING NOT NULL>" │ ├────┼──────────────────────────────┼─────────────────────────────────┼──────────────┼───────────────┼────────────────────────────────┼───────────────────────────────┼─────────────────────────────────┤ │30 │"preExisting_actor_name_age" │"UNIQUENESS" │"NODE" │["Actor"] │["firstname","age"] │"preExisting_actor_name_age" │null │ ├────┼──────────────────────────────┼─────────────────────────────────┼──────────────┼───────────────┼────────────────────────────────┼───────────────────────────────┼─────────────────────────────────┤ │10 │"preExisting_book_published" │"UNIQUENESS" │"NODE" │["Book"] │["published"] │"preExisting_book_published" │null │ ├────┼──────────────────────────────┼─────────────────────────────────┼──────────────┼───────────────┼────────────────────────────────┼───────────────────────────────┼─────────────────────────────────┤ │37 │"preExisting_how" │"RELATIONSHIP_UNIQUENESS" │"RELATIONSHIP"│["KNOWS"] │["how"] │"preExisting_how" │null │ ├────┼──────────────────────────────┼─────────────────────────────────┼──────────────┼───────────────┼────────────────────────────────┼───────────────────────────────┼─────────────────────────────────┤ │15 │"rel_constraint_with_options" │"RELATIONSHIP_UNIQUENESS" │"RELATIONSHIP"│["SEQUEL_OF"] │["order","seriesTitle","number"]│"rel_constraint_with_options" │null │ ├────┼──────────────────────────────┼─────────────────────────────────┼──────────────┼───────────────┼────────────────────────────────┼───────────────────────────────┼─────────────────────────────────┤ │35 │"rel_constraint_with_provider"│"RELATIONSHIP_KEY" │"RELATIONSHIP"│["KNOWS"] │["since"] │"rel_constraint_with_provider" │null │ ├────┼──────────────────────────────┼─────────────────────────────────┼──────────────┼───────────────┼────────────────────────────────┼───────────────────────────────┼─────────────────────────────────┤ │13 │"sequels" │"RELATIONSHIP_UNIQUENESS" │"RELATIONSHIP"│["SEQUEL_OF"] │["order","seriesTitle"] │"sequels" │null │ ├────┼──────────────────────────────┼─────────────────────────────────┼──────────────┼───────────────┼────────────────────────────────┼───────────────────────────────┼─────────────────────────────────┤ │23 │"seriesOrder" │"NODE_PROPERTY_TYPE" │"NODE" │["Movie"] │["seriesOrder"] │null │"INTEGER" │ ├────┼──────────────────────────────┼─────────────────────────────────┼──────────────┼───────────────┼────────────────────────────────┼───────────────────────────────┼─────────────────────────────────┤ │38 │"movie_tagline" │"NODE_PROPERTY_TYPE" │"NODE" │["Movie"] │["tagline"] │null │"STRING | LIST<STRING NOT NULL>" │ ├────┼──────────────────────────────┼─────────────────────────────────┼──────────────┼───────────────┼────────────────────────────────┼───────────────────────────────┼─────────────────────────────────┤ │21 │"wrote_locations" │"RELATIONSHIP_PROPERTY_EXISTENCE"│"RELATIONSHIP"│["WROTE"] │["location"] │null │null │ ├────┼──────────────────────────────┼─────────────────────────────────┼──────────────┼───────────────┼────────────────────────────────┼───────────────────────────────┼─────────────────────────────────┤ │20 │"wrote_year" │"RELATIONSHIP_PROPERTY_EXISTENCE"│"RELATIONSHIP"│["WROTE"] │["year"] │null │null │ └────┴──────────────────────────────┴─────────────────────────────────┴──────────────┴───────────────┴────────────────────────────────┴───────────────────────────────┴─────────────────────────────────┘ 18 rows
The |
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.
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"│ ╞════╪═════════════════╪═════════════════════════════════╪══════════════╪═══════════════╪════════════╪════════════╪══════════════╡ │21 │"wrote_locations"│"RELATIONSHIP_PROPERTY_EXISTENCE"│"RELATIONSHIP"│["WROTE"] │["location"]│null │null │ ├────┼─────────────────┼─────────────────────────────────┼──────────────┼───────────────┼────────────┼────────────┼──────────────┤ │20 │"wrote_year" │"RELATIONSHIP_PROPERTY_EXISTENCE"│"RELATIONSHIP"│["WROTE"] │["year"] │null │null │ └────┴─────────────────┴─────────────────────────────────┴──────────────┴───────────────┴────────────┴────────────┴──────────────┘ 2 rows
Was this page helpful?