创建约束

使用 CREATE CONSTRAINT 命令创建约束。创建约束时,建议提供一个约束名称。该名称在索引和约束中必须是唯一的。如果未显式提供名称,系统将自动生成一个唯一名称。

创建约束需要 CREATE CONSTRAINT 权限
添加约束是一个原子操作,可能需要一些时间——在 Neo4j DBMS 使用约束之前,必须扫描所有现有数据。

创建属性唯一性约束

属性唯一性约束确保具有特定标签的所有节点或具有特定类型的所有关系中的属性值是唯一的。对于涉及多个属性的复合属性唯一性约束,必须保证这些属性值的组合是唯一的。尝试添加重复属性值的查询将会失败。

属性唯一性约束并不要求所有节点或关系都必须包含约束中列出的属性。只有包含约束中所指定的所有属性的节点或关系才受唯一性规则的约束。缺少一个或多个指定属性的节点或关系不受此规则约束。

创建单个属性唯一性约束

使用以下命令创建单个属性唯一性约束:

  • 节点属性唯一性约束:CREATE CONSTRAINT constraint_name FOR (n:Label) REQUIRE n.property IS UNIQUE

  • 关系属性唯一性约束:CREATE CONSTRAINT constraint_name FOR ()-[r:REL_TYPE]-() REQUIRE r.property IS UNIQUE

有关创建属性唯一性约束的完整命令语法,请参阅 语法 → 创建属性唯一性约束

示例 1. 在单个属性上创建节点属性唯一性约束
创建一个约束,要求 Book 节点必须具有唯一的 isbn 属性
CREATE CONSTRAINT book_isbn
FOR (book:Book) REQUIRE book.isbn IS UNIQUE
结果
Added 1 constraint.
示例 2. 在单个属性上创建关系属性唯一性约束
创建一个约束,要求 SEQUEL_OF 关系必须具有唯一的 order 属性
CREATE CONSTRAINT sequels
FOR ()-[sequel:SEQUEL_OF]-() REQUIRE sequel.order IS UNIQUE
结果
Added 1 constraint.

创建复合属性唯一性约束

为多个属性创建的约束称为复合约束。请注意,在创建复合属性唯一性约束时,必须将受约束的属性括在括号内。

  • 节点属性唯一性约束:CREATE CONSTRAINT constraint_name FOR (n:Label) REQUIRE (n.propertyName_1, …​, n.propertyName_n) IS UNIQUE

  • 关系属性唯一性约束:CREATE CONSTRAINT constraint_name FOR ()-[r:REL_TYPE]-() REQUIRE (r.propertyName_1, …​, r.propertyName_n) IS UNIQUE

有关创建属性唯一性约束的完整命令语法,请参阅 语法 → 创建属性唯一性约束

示例 3. 在多个属性上创建复合节点属性唯一性约束
创建一个约束,要求 Book 节点必须具有唯一的 titlepublicationYear 属性组合
CREATE CONSTRAINT book_title_year
FOR (book:Book) REQUIRE (book.title, book.publicationYear) IS UNIQUE
结果
Added 1 constraint.
示例 4. 在多个属性上创建复合关系属性唯一性约束
创建一个约束,要求 PREQUEL_OF 关系必须具有唯一的 orderauthor 属性组合
CREATE CONSTRAINT prequels
FOR ()-[prequel:PREQUEL_OF]-() REQUIRE (prequel.order, prequel.author) IS UNIQUE
结果
Added 1 constraint.

创建符合现有属性唯一性约束的数据

示例 5. 创建符合现有属性唯一性约束的节点
创建一个具有唯一 isbn 属性的 Book 节点
CREATE (book:Book {isbn: '1449356265', title: 'Graph Databases'})
结果
Added 1 label, created 1 node, set 2 properties
示例 6. 创建符合现有属性唯一性约束的关系
创建一个具有唯一 order 属性的 SEQUEL_OF 关系
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.

创建属性存在性约束

属性存在性约束确保某个属性对于具有特定标签的所有节点或具有特定类型的所有关系都存在。尝试在没有该受约束属性的情况下创建指定标签的新节点或指定类型的新关系的查询将会失败。尝试删除强制属性的查询也是如此。

创建单个属性存在性约束

单个属性的存在性约束使用以下命令创建:

  • 节点属性存在性约束:CREATE CONSTRAINT constraint_name FOR (n:Label) REQUIRE n.property IS NOT NULL

  • 关系属性存在性约束:CREATE CONSTRAINT constraint_name FOR ()-[r:REL_TYPE]-() REQUIRE r.property IS NOT NULL

有关创建存在性约束的完整命令语法,请参阅 语法 → 创建属性存在性约束

无法在多个属性上创建复合存在性约束。
示例 7. 创建节点属性存在性约束
创建一个约束,要求 Author 节点必须具有 name 属性
CREATE CONSTRAINT author_name
FOR (author:Author) REQUIRE author.name IS NOT NULL
结果
Added 1 constraint.
示例 8. 创建关系属性存在性约束
创建一个约束,要求 WROTE 关系必须具有 year 属性
CREATE CONSTRAINT wrote_year
FOR ()-[wrote:WROTE]-() REQUIRE wrote.year IS NOT NULL
结果
Added 1 constraint.

创建符合现有属性存在性约束的数据

示例 9. 创建符合现有节点属性存在性约束的节点
创建一个具有 name 属性的 Author 节点
CREATE (author:Author {name:'Virginia Woolf', surname: 'Woolf'})
结果
Added 1 label, created 1 node, set 2 properties
示例 10. 创建符合现有关系属性存在性约束的关系
创建一个具有 year 属性的 WROTE 关系
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})
结果
Added 2 labels, created 2 nodes, set 7 properties, created 1 relationship

创建属性类型约束

属性类型约束确保属性对于具有特定标签的所有节点或具有特定类型的所有关系都具有所需的数据类型。尝试添加数据类型不正确的属性,或者以改变指定标签节点或指定类型关系的数据类型的方式修改属性的查询将会失败。

属性类型约束并不要求所有节点或关系都必须具有该属性。没有受约束属性的节点或关系不受此规则约束。

创建单个属性类型约束

属性类型约束使用以下命令创建:

  • 节点属性类型约束:CREATE CONSTRAINT constraint_name FOR (n:Label) REQUIRE n.property IS :: <TYPE>

  • 关系属性类型约束:CREATE CONSTRAINT constraint_name FOR ()-[r:REL_TYPE]-() REQUIRE r.property IS :: <TYPE>

<TYPE> 指的是特定的 Cypher® 数据类型,例如 STRINGINTEGER。有关属性可受约束的类型,请参阅 允许的类型;有关 Cypher 中不同数据类型的信息,请参阅 值和类型。有关创建属性类型约束的完整命令语法,请参阅 语法 → 创建属性类型约束

无法在多个属性上创建复合属性类型约束。
示例 11. 创建节点属性类型约束
创建一个约束,要求 Movie 节点上的 title 属性必须为 STRING 类型
CREATE CONSTRAINT movie_title
FOR (movie:Movie) REQUIRE movie.title IS :: STRING
结果
Added 1 constraint.
示例 12. 创建关系属性类型约束
创建一个约束,要求 PART_OF 关系上的 order 属性必须为 INTEGER 类型
CREATE CONSTRAINT part_of
FOR ()-[part:PART_OF]-() REQUIRE part.order IS :: INTEGER
结果
Added 1 constraint.
示例 13. 创建 VECTOR 属性类型约束 仅限 Cypher 25 引入于 Neo4j 2025.10

必须为任何受约束的 VECTOR 属性指定维度和坐标类型。维度必须大于 0 且小于等于 4096。有关更多信息,请参阅 值和类型 → 向量

创建一个约束,要求 Movie 节点上的 embedding 属性必须为 VECTOR<INT32>(42) 类型
CREATE CONSTRAINT node_vector_constraint
FOR (n:Movie) REQUIRE n.embedding IS :: VECTOR<INT32>(42)
结果
Added 1 constraint.
创建一个约束,要求 CONTAINS 关系上的 embedding 属性必须为 VECTOR<FLOAT32>(1536) 类型
CREATE CONSTRAINT rel_vector_constraint
FOR ()-[r:CONTAINS]->() REQUIRE r.embedding IS :: VECTOR<FLOAT32>(1536)
结果
Added 1 constraint.

创建联合类型的属性类型约束

闭合动态联合类型允许节点或关系属性保持一定的类型灵活性,同时防止存储意外的值。

示例 14. 创建具有联合类型的节点属性类型约束
创建一个约束,要求 Movie 节点上的 tagline 属性必须为 STRINGLIST<STRING NOT NULL> 类型
CREATE CONSTRAINT movie_tagline
FOR (movie:Movie) REQUIRE movie.tagline IS :: STRING | LIST<STRING NOT NULL>
结果
Added 1 constraint.
示例 15. 创建具有联合类型的关系属性类型约束
创建一个约束,要求 PART_OF 关系上的 tags 属性必须为 STRINGLIST<STRING NOT NULL> 类型
CREATE CONSTRAINT part_of_tags
FOR ()-[part:PART_OF]-() REQUIRE part.tags IS :: STRING | LIST<STRING NOT NULL>
结果
Added 1 constraint.

允许的类型

属性类型约束允许的属性类型包括:

  • 布尔值 (BOOLEAN)

  • STRING

  • INTEGER(整数)

  • FLOAT

  • DATE

  • LOCAL TIME

  • ZONED TIME

  • LOCAL DATETIME

  • ZONED DATETIME

  • DURATION(持续时间)

  • POINT

  • VECTOR<TYPE>(DIMENSION) 仅限 Cypher 25 引入于 Neo4j 2025.10

  • LIST<BOOLEAN NOT NULL>

  • LIST<STRING NOT NULL>

  • LIST<INTEGER NOT NULL>

  • LIST<FLOAT NOT NULL>

  • LIST<DATE NOT NULL>

  • LIST<LOCAL TIME NOT NULL>

  • LIST<ZONED TIME NOT NULL>

  • LIST<LOCAL DATETIME NOT NULL>

  • LIST<ZONED DATETIME NOT NULL>

  • LIST<DURATION NOT NULL>

  • LIST<POINT NOT NULL>

  • 上述类型的任何闭合动态联合,例如 INTEGER | FLOAT | STRING

由于不支持存储 VECTOR 值列表,因此无法为 LIST<VECTOR<TYPE>(DIMENSION) NOT NULL> 创建属性类型约束。此外,VECTOR 属性类型约束必须使用特定的维度和坐标值创建,其中维度必须大于 0 且小于等于 4096。有关更多信息,请参阅 值和类型 → 向量

有关描述 Cypher 中所有可用类型的完整参考,请参阅关于 类型及其同义词 的部分。

创建无效类型的属性类型约束将会失败

示例 16. 创建具有无效类型的节点属性类型约束
创建一个约束,要求 Movie 节点上的 imdbScore 属性必须为 MAP 类型
CREATE CONSTRAINT score FOR (movie:Movie) REQUIRE movie.imdbScore IS :: MAP
GQLSTATUS 错误链

22N90: 错误: 数据异常 - 约束中不支持该属性类型。属性类型约束中不支持 MAP。

50N11: 错误: 一般处理异常 - 约束创建失败。无法创建“节点属性类型约束”。

创建符合现有属性类型约束的数据

示例 17. 创建符合现有节点属性类型约束的节点
创建一个具有 STRING 类型 title 属性的 Movie 节点
CREATE (movie:Movie {title:'Iron Man'})
结果
Added 1 label, created 1 node, set 1 properties
示例 18. 创建符合现有关系属性类型约束的关系
创建一个具有 INTEGER 类型 order 属性的 PART_OF 关系
MATCH (movie:Movie {title:'Iron Man'})
CREATE (movie)-[part:PART_OF {order: 3}]->(franchise:Franchise {name:'MCU'})
结果
Added 1 label, added 1 node, created 1 relationship, set 2 properties

创建键约束

键约束确保属性存在,且属性值对于具有特定标签的所有节点或具有特定类型的所有关系都是唯一的。对于多个属性的复合键约束,所有属性必须存在,且属性值的组合必须是唯一的。

尝试在没有受约束属性的情况下创建具有指定标签的新节点或具有指定类型的新关系的查询将会失败。删除强制属性或添加重复属性值的查询也是如此。

创建单个属性键约束

单个属性键约束使用以下命令创建:

  • 节点键约束:CREATE CONSTRAINT constraint_name FOR (n:Label) REQUIRE n.property IS NODE KEY

  • 关系键约束:CREATE CONSTRAINT constraint_name FOR ()-[r:REL_TYPE]-() REQUIRE r.property IS RELATIONSHIP KEY

有关创建键约束的完整命令语法,请参阅 语法 → 创建键约束

示例 19. 在单个属性上创建节点键约束
创建一个约束,要求 Director 节点必须具有唯一的 imdbId 属性作为节点键。
CREATE CONSTRAINT director_imdbId
FOR (director:Director) REQUIRE (director.imdbId) IS NODE KEY
结果
Added 1 constraint.
示例 20. 在单个属性上创建关系键约束
创建一个约束,要求 OWNS 关系必须具有唯一的 ownershipId 属性作为关系键
CREATE CONSTRAINT ownershipId
FOR ()-[owns:OWNS]-() REQUIRE owns.ownershipId IS RELATIONSHIP KEY
结果
Added 1 constraint.

创建复合键约束

为多个属性创建的约束称为复合约束。请注意,在创建复合键约束时,必须将受约束的属性括在括号内。

复合键约束使用以下命令创建:

  • 节点键约束:CREATE CONSTRAINT constraint_name FOR (n:Label) REQUIRE (n.propertyName_1, …​, n.propertyName_n) IS NODE KEY

  • 关系键约束:CREATE CONSTRAINT constraint_name FOR ()-[r:REL_TYPE]-() REQUIRE (r.propertyName_1, …​, r.propertyName_n) IS RELATIONSHIP KEY

有关创建键约束的完整命令语法,请参阅 语法 → 创建键约束

示例 21. 在多个属性上创建复合节点键约束
创建一个约束,要求 Actor 节点必须具有唯一的 firstnamesurname 属性组合作为节点键
CREATE CONSTRAINT actor_fullname
FOR (actor:Actor) REQUIRE (actor.firstname, actor.surname) IS NODE KEY
结果
Added 1 constraint.
示例 22. 在多个属性上创建复合关系键约束
创建一个约束,要求 KNOWS 关系必须具有唯一的 sincehow 属性组合作为关系键
CREATE CONSTRAINT knows_since_how
FOR ()-[knows:KNOWS]-() REQUIRE (knows.since, knows.how) IS RELATIONSHIP KEY
结果
Added 1 constraint.

创建符合现有键约束的数据

示例 23. 创建符合现有节点键约束的节点
创建一个具有唯一 firstnamesurname 属性的 Actor 节点
CREATE (actor:Actor {firstname: 'Keanu', surname: 'Reeves'})
结果
Added 1 label, created 1 node, set 2 properties.
示例 24. 创建符合现有关系键约束的关系
创建一个具有唯一 sincehow 属性的 KNOWS 关系
CREATE (:Actor {firstname: 'Jensen', surname: 'Ackles'})-[:KNOWS {since: 2008, how: 'coworkers', friend: true}]->(:Actor {firstname: 'Misha', surname: 'Collins'})
结果
Added 2 labels, created 2 nodes, set 7 properties, created 1 relationship.

使用参数创建约束

所有约束类型都可以使用参数化名称进行创建。

示例 25. 使用参数创建节点属性唯一性约束
参数
{
  "name": "node_uniqueness_param"
}
使用参数化名称创建节点属性唯一性约束
CREATE CONSTRAINT $name
FOR (book:Book) REQUIRE book.prop1 IS UNIQUE
结果
Added 1 constraint.
示例 26. 使用参数创建关系属性存在性约束
参数
{
  "name": "rel_exist_param"
}
使用参数化名称创建关系属性存在性约束
CREATE CONSTRAINT $name
FOR ()-[wrote:WROTE]-() REQUIRE wrote.published IS NOT NULL
结果
Added 1 constraint.

处理多个约束

创建已经存在的约束将会失败。这包括以下情况:

  • 创建与现有约束完全相同的约束。

  • 创建名称不同,但与现有约束属于同一约束类型、作用于相同标签/关系类型且属性组合也相同的约束。对于属性类型约束,属性类型也必须相同。

  • 创建名称与现有约束相同(无论该现有约束是什么类型)的约束。

此外,某些约束不能共存,因此尝试同时创建它们也会失败。这包括:

  • 在相同标签/关系类型和属性上存在具有不同类型的属性类型约束。这包括具有不同维度或坐标类型的 VECTOR 类型。

  • 在相同标签/关系类型和属性组合上同时存在属性唯一性约束和键约束。

但是,某些约束类型在相同标签/关系类型和属性组合上是允许的。例如,可以同时在相同标签/关系类型和属性组合上拥有属性唯一性约束和属性存在性约束,但这相当于拥有了一个节点或关系键约束。更有用的例子是结合属性类型约束和属性存在性约束,以确保该属性既存在又具有指定的类型。

创建约束时处理现有约束

为了避免因现有约束而失败,可以在 CREATE 命令中添加 IF NOT EXISTS。这可以确保如果存在具有给定名称的约束,或者在相同约束类型和模式上存在另一个约束,则不会抛出错误,也不会创建新约束。对于属性类型约束,属性类型也必须相同。相反,系统将返回一个信息性通知,显示阻止创建的现有约束。

示例 27. 创建与现有约束相同的约束
创建一个要求所有 SEQUEL_OF 关系具有唯一 order 属性的约束
CREATE CONSTRAINT sequels IF NOT EXISTS
FOR ()-[sequel:SEQUEL_OF]-() REQUIRE sequel.order IS UNIQUE

由于相同的约束已经存在,因此不会执行任何操作

结果
(no changes, no records)
通知
`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) IS UNIQUE` already exists.
示例 28. 当相同约束但名称不同已存在时,创建关系属性唯一性约束
创建一个要求所有 SEQUEL_OF 关系具有唯一 order 属性的约束
CREATE CONSTRAINT new_sequels IF NOT EXISTS
FOR ()-[sequel:SEQUEL_OF]-() REQUIRE sequel.order IS UNIQUE

由于在相同模式上已存在名称不同(sequels)的约束,因此不会执行任何操作

结果
(no changes, no records)
通知
`CREATE CONSTRAINT new_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) IS UNIQUE` already exists.
示例 29. 创建名称与不同类型的现有约束相同(但约束类型不同)的约束
创建一个要求所有 AUTHORED 关系具有唯一 name 属性的约束
CREATE CONSTRAINT author_name IF NOT EXISTS
FOR ()-[a:AUTHORED]-() REQUIRE a.name IS UNIQUE

由于已经存在名为 author_name 的节点属性存在性约束,因此不会执行任何操作

结果
(no changes, no records)
通知
`CREATE CONSTRAINT author_name IF NOT EXISTS FOR ()-[e:AUTHORED]-() REQUIRE (e.name) IS UNIQUE` has no effect.
`CONSTRAINT author_name FOR (e:Author) REQUIRE (e.name) IS NOT NULL` already exists.

创建已经存在的约束将会失败

如果创建的约束名称相同,或者在相同节点标签或关系类型以及已被相同类型约束的属性上创建约束,将会失败。属性唯一性约束和键约束也不允许在相同的模式上同时存在。

示例 30. 创建与现有约束完全相同的约束
在已存在相同约束的情况下,创建一个要求所有 SEQUEL_OF 关系具有唯一 order 属性的约束
CREATE CONSTRAINT sequels
FOR ()-[sequel:SEQUEL_OF]-() REQUIRE sequel.order IS UNIQUE
GQLSTATUS 错误链

22N65: 错误: 数据异常 - 等效约束已存在。等效约束已存在:'sequels'

示例 31. 创建名称不同但作用于相同模式的约束
在已存在该模式约束的情况下,创建一个要求所有 Book 节点具有唯一 isbn 属性的约束
CREATE CONSTRAINT new_book_isbn
FOR (book:Book) REQUIRE book.isbn IS UNIQUE
GQLSTATUS 错误链

22N65: 错误: 数据异常 - 等效约束已存在。等效约束已存在:'Constraint( id=3, name='book_isbn', type='NODE PROPERTY UNIQUENESS', schema=(:Book {isbn}), ownedIndex=2 )'

示例 32. 创建名称相同但作用于不同模式的约束
在已存在具有相同名称的约束但作用于不同模式的情况下,创建一个要求所有 AUTHORED 关系具有唯一 name 属性的约束
CREATE CONSTRAINT author_name
FOR ()-[a:AUTHORED]-() REQUIRE a.name IS UNIQUE
GQLSTATUS 错误链

22N67: 错误: 数据异常 - 约束名称重复。名称相同的约束已存在:author_name

示例 33. 当已存在将属性限制为不同类型的属性类型约束时,在该属性上创建属性类型约束
在已存在要求 PART_OF 关系上的 order 属性为 INTEGER 类型的约束的情况下,创建一个要求该属性为 FLOAT 类型的约束
CREATE CONSTRAINT new_part_of
FOR ()-[part:PART_OF]-() REQUIRE part.order IS :: FLOAT
GQLSTATUS 错误链

22N66: 错误: 数据异常 - 冲突约束已存在。冲突约束已存在:'Constraint( id=13, name='part_of', type='RELATIONSHIP PROPERTY TYPE', schema=()-[:PART_OF {order}]-(), propertyType=INTEGER )'

示例 34. 在已有属性唯一性约束的模式上创建节点键约束
在已有属性唯一性约束的情况下,针对 Book 标签节点上的 titlepublicationYear 属性创建节点键约束
CREATE CONSTRAINT book_titles FOR (book:Book) REQUIRE (book.title, book.publicationYear) IS NODE KEY
GQLSTATUS 错误链

22N66: 错误: 数据异常 - 冲突约束已存在。冲突约束已存在:'Constraint( id=7, name='book_title_year', type='NODE PROPERTY UNIQUENESS', schema=(:Book {title, publicationYear}), ownedIndex=6 )'

约束与索引

约束与底层索引

属性唯一性约束和键约束由 范围索引 (range indexes) 提供支持。这意味着创建属性唯一性约束或键约束时,会创建一个与该约束同名、具有相同节点标签/关系类型和属性组合的范围索引。单个属性约束将创建单个属性索引,多个属性的复合约束将创建 复合索引

具有相同索引类型、标签/关系类型和属性组合的索引不能单独添加。但是,删除属性唯一性约束或键约束也会同时删除其支持索引。如果该支持索引仍有必要,则需要显式重新创建。

属性唯一性约束和键约束需要索引,因为它允许系统快速检查是否已存在具有相同标签和属性值(或相同类型和属性值)的节点或关系。没有索引,系统将需要扫描所有具有相同标签的节点,这在图规模增大时会非常缓慢且低效。索引通过支持直接查找而非全图扫描,使这些检查变得快得多。Cypher 将使用拥有约束的索引,方式与利用其他搜索性能索引相同。有关索引如何影响查询性能的更多信息,请参阅 索引对查询性能的影响

这些索引列在 SHOW INDEX 命令返回的 owningConstraint 列中,以及 SHOW CONSTRAINT 命令返回的 ownedIndex 列中。

示例 35. 列出带有底层索引的约束
查询
SHOW CONSTRAINTS WHERE ownedIndex IS NOT NULL
结果
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id | name                    | type                               | entityType     | labelsOrTypes  | properties                   | ownedIndex              | propertyType |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 21 | "actor_fullname"        | "NODE_KEY"                         | "NODE"         | ["Actor"]      | ["firstname", "surname"]     | "actor_fullname"        | NULL         |
| 3  | "book_isbn"             | "NODE_PROPERTY_UNIQUENESS"         | "NODE"         | ["Book"]       | ["isbn"]                     | "book_isbn"             | NULL         |
| 7  | "book_title_year"       | "NODE_PROPERTY_UNIQUENESS"         | "NODE"         | ["Book"]       | ["title", "publicationYear"] | "book_title_year"       | NULL         |
| 17 | "director_imdbId"       | "NODE_KEY"                         | "NODE"         | ["Director"]   | ["imdbId"]                   | "director_imdbId"       | NULL         |
| 23 | "knows_since_how"       | "RELATIONSHIP_KEY"                 | "RELATIONSHIP" | ["KNOWS"]      | ["since", "how"]             | "knows_since_how"       | NULL         |
| 25 | "node_uniqueness_param" | "NODE_PROPERTY_UNIQUENESS"         | "NODE"         | ["Book"]       | ["prop1"]                    | "node_uniqueness_param" | NULL         |
| 19 | "ownershipId"           | "RELATIONSHIP_KEY"                 | "RELATIONSHIP" | ["OWNS"]       | ["ownershipId"]              | "ownershipId"           | NULL         |
| 9  | "prequels"              | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"]          | "prequels"              | NULL         |
| 5  | "sequels"               | "RELATIONSHIP_PROPERTY_UNIQUENESS" | "RELATIONSHIP" | ["SEQUEL_OF"]  | ["order"]                    | "sequels"               | NULL         |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
示例 36. 列出带有拥有约束的索引
查询
SHOW INDEXES WHERE owningConstraint IS NOT NULL
结果
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id | name                    | state    | populationPercent | type    | entityType     | labelsOrTypes  | properties                   | indexProvider | owningConstraint        | lastRead                 | readCount |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| 20 | "actor_fullname"        | "ONLINE" | 100.0             | "RANGE" | "NODE"         | ["Actor"]      | ["firstname", "surname"]     | "range-1.0"   | "actor_fullname"        | 2024-10-07T12:12:51.893Z | 3         |
| 2  | "book_isbn"             | "ONLINE" | 100.0             | "RANGE" | "NODE"         | ["Book"]       | ["isbn"]                     | "range-1.0"   | "book_isbn"             | 2024-10-07T11:58:09.252Z | 2         |
| 6  | "book_title_year"       | "ONLINE" | 100.0             | "RANGE" | "NODE"         | ["Book"]       | ["title", "publicationYear"] | "range-1.0"   | "book_title_year"       | NULL                     | 0         |
| 16 | "director_imdbId"       | "ONLINE" | 100.0             | "RANGE" | "NODE"         | ["Director"]   | ["imdbId"]                   | "range-1.0"   | "director_imdbId"       | NULL                     | 0         |
| 22 | "knows_since_how"       | "ONLINE" | 100.0             | "RANGE" | "RELATIONSHIP" | ["KNOWS"]      | ["since", "how"]             | "range-1.0"   | "knows_since_how"       | 2024-10-07T12:12:51.894Z | 1         |
| 24 | "node_uniqueness_param" | "ONLINE" | 100.0             | "RANGE" | "NODE"         | ["Book"]       | ["prop1"]                    | "range-1.0"   | "node_uniqueness_param" | NULL                     | 0         |
| 18 | "ownershipId"           | "ONLINE" | 100.0             | "RANGE" | "RELATIONSHIP" | ["OWNS"]       | ["ownershipId"]              | "range-1.0"   | "ownershipId"           | NULL                     | 0         |
| 8  | "prequels"              | "ONLINE" | 100.0             | "RANGE" | "RELATIONSHIP" | ["PREQUEL_OF"] | ["order", "author"]          | "range-1.0"   | "prequels"              | NULL                     | 0         |
| 4  | "sequels"               | "ONLINE" | 100.0             | "RANGE" | "RELATIONSHIP" | ["SEQUEL_OF"]  | ["order"]                    | "range-1.0"   | "sequels"               | 2024-10-07T11:57:12.999Z | 1         |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
属性存在性约束和属性类型约束不由索引支持。

约束失败与索引

尝试创建与现有索引同名的任何类型的约束都会失败。

示例 37. 创建与现有索引同名的节点属性类型约束
创建一个名为 directors 的索引
CREATE INDEX directors FOR (director:Director) ON (director.name)
创建一个名为 directors 的节点属性类型约束
CREATE CONSTRAINT directors FOR (movie:Movie) REQUIRE movie.director IS :: STRING
GQLSTATUS 错误链

22N71: 错误: 数据异常 - 索引名称重复。同名索引已存在:directors

在已有索引的模式上创建键约束或属性唯一性约束将会失败。

示例 38. 在已有索引的模式上创建节点属性唯一性约束
Book 节点上的 wordCount 属性创建一个索引
CREATE INDEX book_word_count FOR (book:Book) ON (book.wordCount)
创建一个要求所有 Book 节点具有唯一 wordCount 属性的约束
CREATE CONSTRAINT word_count FOR (book:Book) REQUIRE book.wordCount IS UNIQUE
GQLSTATUS 错误链

22N73: 错误: 数据异常 - 约束与现有索引冲突。约束与已存在的索引 '(:Book {wordCount})' 冲突。

约束与数据违规场景

创建违反现有约束的数据将会失败

现有约束阻止数据创建
约束类型 创建没有存在性约束属性的节点和关系 创建具有非唯一属性/属性组合的节点和关系 创建属性类型错误的节点和关系

属性唯一性约束

属性存在性约束

属性类型约束

键约束

示例 39. 创建违反节点属性唯一性约束的节点
创建一个 isbn 属性已存在的 Book 节点
CREATE (book:Book {isbn: '1449356265', title: 'Graph Databases'})
GQLSTATUS 错误链

22N80: 错误: 数据异常 - 索引条目冲突。索引条目冲突:节点 (0) 已存在,标签为 Book,属性 isbn = '1449356265'。

22N79: 错误: 数据异常 - 违反属性唯一性约束。违反属性唯一性约束:节点 (0) 已存在,标签为 Book,属性 isbn = '1449356265'。

示例 40. 创建违反现有节点属性存在性约束的节点
在存在 :Author(name) 存在性约束的情况下,创建一个没有 name 属性的 Author 节点
CREATE (author:Author {surname: 'Austen'})
GQLSTATUS 错误链

22N77: 错误: 数据异常 - 属性存在性验证失败。带有标签 'Author' 的节点 (11) 必须具有以下属性:name

示例 41. 创建违反现有关系属性类型约束的关系
在存在限制 order 属性为 INTEGER 类型的 PART_OF 关系属性类型约束的情况下,创建一个具有 STRING 类型 order 属性的 PART_OF 关系
MATCH (movie:Movie {title:'Iron Man'}), (franchise:Franchise {name:'MCU'})
CREATE (movie)-[part:PART_OF {order: '1'}]->(franchise)
GQLSTATUS 错误链

22N78: 错误: 数据异常 - 属性类型验证失败。类型为 'PART_OF' 的关系 (1155176602955415558) 必须具有属性 order,且值类型为 INTEGER。

示例 42. 创建违反现有节点键约束的节点
在存在 :Actor(firstname, surname) 节点键约束的情况下,创建一个没有 firstname 属性的 Actor 节点
CREATE (actor:Actor {surname: 'Wood'})
GQLSTATUS 错误链

22N77: 错误: 数据异常 - 属性存在性验证失败。带有标签 'Actor' 的节点 (11) 必须具有以下属性:firstname, surname

删除受存在性约束和键约束的属性将会失败

示例 43. 删除节点属性存在性约束属性
在存在 :Author(name) 存在性约束的情况下,从现有的 Author 节点中删除 name 属性
MATCH (author:Author {name: 'Virginia Woolf'})
REMOVE author.name
GQLSTATUS 错误链

22N77: 错误: 数据异常 - 属性存在性验证失败。带有标签 'Author' 的节点 (3) 必须具有以下属性:name

示例 44. 删除节点键约束属性
在存在 :Actor(firstname, surname) 节点键约束的情况下,从现有的 Actor 节点中删除 firstname 属性
MATCH (actor:Actor {firstname: 'Keanu', surname: 'Reeves'})
REMOVE actor.firstname
GQLSTATUS 错误链

22N77: 错误: 数据异常 - 属性存在性验证失败。带有标签 'Actor' 的节点 (8) 必须具有以下属性:firstname, surname

修改受类型约束的属性将会失败

示例 45. 修改受类型约束的属性
在存在要求 title 属性为 STRING 类型的约束的情况下,将 Movie 'Iron Man' 的 title 修改为 INTEGER
MATCH (m:Movie {title: 'Iron Man'})
SET m.title = 13
GQLSTATUS 错误链

22N78: 错误: 数据异常 - 属性类型验证失败。带有标签 'Movie' 的节点 (6) 必须具有属性 title,且值类型为 STRING。

在存在冲突数据的情况下创建约束将会失败

现有数据阻止约束创建
约束类型 不存在属性 非唯一属性/属性组合 属性类型错误

属性唯一性约束

属性存在性约束

属性类型约束

键约束

示例 46. 在存在冲突节点的情况下创建节点属性唯一性约束
创建两个 name 属性值相同的 Book 节点
CREATE (:Book {isbn: '9780393972832', title: 'Moby Dick'}),
       (:Book {isbn: '9780763630188', title: 'Moby Dick'})
在已存在两个 title 相同的 Book 节点的情况下,创建一个要求 Book 节点具有唯一 title 属性的约束
CREATE CONSTRAINT book_title FOR (book:Book) REQUIRE book.title IS UNIQUE

在这种情况下,由于与现有图冲突,无法创建该约束。请改用 索引,或者删除/更正冲突节点,然后重新应用约束。

GQLSTATUS 错误链

22N80: 错误: 数据异常 - 索引条目冲突。索引条目冲突:节点 (11) 和节点 (12) 都具有标签 Book 且属性 title = 'Moby Dick'。

22N79: 错误: 数据异常 - 违反属性唯一性约束。违反属性唯一性约束:节点 (11) 和节点 (12) 都具有标签 Book 且属性 title = 'Moby Dick'。

50N11: 错误: 一般处理异常 - 约束创建失败。无法创建 'book_title'。

约束创建在发现第一个冲突节点时就会失败。这并不能保证图中没有其他冲突节点。因此,在重新尝试创建约束之前,应检查并清理所有数据。

查找上述约束中具有非唯一属性值的所有冲突节点
MATCH (book1:Book), (book2:Book)
WHERE book1.title = book2.title AND NOT book1 = book2
RETURN book1, book2
示例 47. 在存在冲突关系的情况下创建关系属性存在性约束
在已存在一个没有 language 属性的 WROTE 关系的情况下,创建一个要求所有 WROTE 关系具有 language 属性的约束
CREATE CONSTRAINT wrote_language FOR ()-[wrote:WROTE]-() REQUIRE wrote.language IS NOT NULL

在这种情况下,由于与现有图冲突,无法创建该约束。删除或更正冲突关系,然后重新应用约束。

GQLSTATUS 错误链

22N77: 错误: 数据异常 - 属性存在性验证失败。类型为 'WROTE' 的关系 (1152923703630102532) 必须具有以下属性:language

50N11: 错误: 一般处理异常 - 约束创建失败。无法创建 'Constraint( type='RELATIONSHIP PROPERTY EXISTENCE', schema=()-[:WROTE {language}]-() )'。

约束创建在发现第一个冲突关系时就会失败。这并不能保证图中没有其他冲突关系。因此,在重新尝试创建约束之前,应检查并清理所有数据。

查找上述约束中缺失属性的所有冲突关系
MATCH ()-[wrote:WROTE]-()
WHERE wrote.language IS NULL
RETURN wrote
查找阻止特定约束创建的属性的通用 MATCH 查询
约束 查询

节点属性唯一性约束

MATCH (n1:Label), (n2:Label)
WHERE n1.prop = n2.prop AND NOT n1 = n2
RETURN n1, n2

关系属性唯一性约束

MATCH ()-[r1:REL_TYPE]->(), ()-[r2:REL_TYPE]->()
WHERE r1.prop = r2.prop AND NOT r1 = r2
RETURN r1, r2

节点属性存在性约束

MATCH (n:Label)
WHERE n.prop IS NULL
RETURN n

关系属性存在性约束

MATCH ()-[r:REL_TYPE]->()
WHERE r.prop IS NULL
RETURN r

节点属性类型约束

MATCH (n:Label)
WHERE n.prop IS NOT :: <TYPE>
RETURN n

关系属性类型约束

MATCH ()-[r:REL_TYPE]->()
WHERE r.prop IS NOT :: <TYPE>
RETURN r

节点键约束

MATCH (n1:Label), (n2:Label)
WHERE n1.prop = n2.prop AND NOT n1 = n2
UNWIND [n1, n2] AS node
RETURN node, 'non-unique' AS reason
UNION
MATCH (n:Label)
WHERE n.prop IS NULL
RETURN n AS node, 'non-existing' AS reason

关系键约束

MATCH ()-[r1:REL_TYPE]->(), ()-[r2:REL_TYPE]->()
WHERE r1.prop = r2.prop AND NOT r1 = r2
UNWIND [r1, r2] AS relationship
RETURN relationship, 'non-unique' AS reason
UNION
MATCH ()-[r:REL_TYPE]->()
WHERE r.prop IS NULL
RETURN r AS relationship, 'non-existing' AS reason
© . This site is unofficial and not affiliated with Neo4j, Inc.