创建索引

创建索引可以使用 CREATE [index_type] INDEX [index_name] 命令。如果创建命令中未指定索引类型,则会创建一个范围索引 (range index)

以下索引类型属于此类别

建议在创建索引时为其命名。如果未明确命名,索引将获得一个自动生成的名称。

索引名称必须在所有索引和约束中保持唯一。

CREATE INDEX 命令可以选择性地保持幂等性。这意味着其默认行为是:如果尝试创建同一个索引两次,会抛出错误。如果在命令后添加 IF NOT EXISTS,则不会抛出错误,且如果已存在同名或同模式且类型相同的索引,则不会执行任何操作。如果存在冲突的约束(例如具有相同名称或相同模式及底层索引类型的约束),它仍可能抛出错误。相反,系统会返回一条信息性通知,显示阻碍创建的现有索引。

可以使用 OPTIONS 子句指定索引配置设置。但并非所有索引都有可用的配置设置。在这种情况下,无需指定任何内容,且应在查询中省略 OPTIONS 映射。

创建索引需要 CREATE INDEX 权限

当索引的 statePOPULATING(在创建后立即发生)时,无法使用该索引。要检查索引的 state —— 它是 ONLINE(可用)还是 POPULATING(仍在构建中;populationPercent 列显示索引创建的进度)—— 请运行以下命令:SHOW INDEXES

创建范围索引

创建范围索引可以使用 CREATE INDEX 命令。注意,索引名称必须唯一。

范围索引没有支持的索引配置。

支持的谓词

范围索引支持大多数类型的谓词

谓词 语法

相等性检查。

n.prop = value

列表成员资格检查。

n.prop IN list

存在性检查。

n.prop IS NOT NULL

范围搜索。

n.prop > value

前缀搜索。

STARTS WITH

示例

为节点创建单属性范围索引

以下语句为所有标记为 Person 且具有 surname 属性的节点创建了一个命名范围索引。

创建单属性节点范围索引
CREATE INDEX node_range_index_name FOR (n:Person) ON (n.surname)

为关系创建单属性范围索引

以下语句为所有关系类型为 KNOWS 且具有 since 属性的关系创建了一个命名范围索引。

创建单属性关系范围索引
CREATE INDEX rel_range_index_name FOR ()-[r:KNOWS]-() ON (r.since)

为节点创建复合范围索引

多属性上的范围索引也称为复合索引。对于节点范围索引,只有同时包含指定标签和所有指定属性的节点才会被添加到索引中。

以下语句为所有标记为 Person 且同时具有 agecountry 属性的节点创建了一个命名复合范围索引。

创建多属性复合节点范围索引
CREATE INDEX composite_range_node_index_name FOR (n:Person) ON (n.age, n.country)

为关系创建复合范围索引

多属性上的范围索引也称为复合索引。对于关系范围索引,只有同时具有指定类型和所有指定属性的关系才会被添加到索引中。

以下语句为所有标记为 PURCHASED 且同时具有 dateamount 属性的关系创建了一个命名复合范围索引。

创建多属性复合关系范围索引
CREATE INDEX composite_range_rel_index_name FOR ()-[r:PURCHASED]-() ON (r.date, r.amount)

使用参数创建范围索引

以下语句使用参数作为索引名称,为所有带有 Person 标签且具有 firstname 属性的节点创建一个命名范围索引。

参数
{
  "name": "range_index_param"
}
创建单属性节点范围索引
CREATE INDEX $name FOR (n:Person) ON (n.firstname)

仅在索引不存在时创建范围索引

如果不知道索引是否存在,请添加 IF NOT EXISTS 以确保其存在。

使用 IF NOT EXISTS 创建范围索引
CREATE INDEX node_range_index_name IF NOT EXISTS
FOR (n:Person) ON (n.surname)

如果已存在具有相同模式和类型、相同名称或两者的索引,则不会创建新索引。系统会返回一条信息性通知。

通知
`CREATE RANGE INDEX node_range_index_name IF NOT EXISTS FOR (e:Person) ON (e.surname)` has no effect.
`RANGE INDEX node_range_index_name FOR (e:Person) ON (e.surname)` already exists.

创建文本索引

创建文本索引可以使用 CREATE TEXT INDEX 命令。注意,索引名称必须唯一。

文本索引没有支持的索引配置。

有关文本索引如何处理 STRING 值的信息,请参阅 Trigram 索引

支持的谓词

文本索引仅处理作用于 STRING 值的谓词。

以下仅作用于 STRING 值的谓词始终可由文本索引解决

  • STARTS WITH

  • ENDS WITH

  • CONTAINS

但是,其他谓词仅在已知属性与 STRING 进行比较时才会被使用

  • n.prop = "string"

  • n.prop IN ["a", "b", "c"]

这意味着文本索引无法解决例如 a.prop = b.prop,除非该属性上同时存在属性类型约束

文本索引支持以下谓词

谓词 语法

相等性检查。

n.prop = 'example_string'

列表成员资格检查。

n.prop IN ['abc', 'example_string', 'neo4j']

前缀搜索。

STARTS WITH

后缀搜索。

ENDS WITH

子字符串搜索。

CONTAINS

上述谓词集可以通过类型约束进行扩展。有关更多信息,请参阅关于 索引兼容性和类型约束 的章节。

文本索引仅用于精确查询匹配。若要执行模糊匹配(例如包含变体和拼写错误),以及计算 STRING 值之间的相似度得分,请改用语义 全文索引

Trigram 索引

文本索引使用 Trigram 索引。这意味着 STRING 值被索引为重叠的 Trigram,每个 Trigram 包含三个 Unicode 码点。例如,单词 "developer" 将被以下 Trigram 索引:["dev", "eve", "vel", "elo", "lop", "ope", "per"]

这使得文本索引特别适合子字符串 (CONTAINS) 和后缀 (ENDS WITH) 搜索,以及前缀 (STARTS WITH) 搜索。例如,像 CONTAINS "vel"ENDS WITH "per" 这样的搜索可以通过直接在索引中查找相关的 Trigram 来高效执行。相比之下,按字典顺序索引 STRING 值的范围索引(更多信息请参阅 范围索引支持的 ORDER BY)更适合前缀搜索,但如果要在文本中查找 "vel",则需要扫描所有索引值。有关更多信息,请参阅 索引对查询性能的影响 → 文本索引

示例

创建节点文本索引

以下语句为所有标记为 Person 且具有 nickname STRING 属性的节点创建了一个命名文本索引。

创建单属性节点文本索引
CREATE TEXT INDEX node_text_index_nickname FOR (n:Person) ON (n.nickname)

创建关系文本索引

以下语句为所有具有关系类型 KNOWSSTRING 属性 interest 的关系创建了一个命名文本索引。

创建单属性关系文本索引
CREATE TEXT INDEX rel_text_index_name FOR ()-[r:KNOWS]-() ON (r.interest)

使用参数创建文本索引

以下语句使用参数作为索引名称,为所有带有 Person 标签且具有 favoriteColor STRING 属性的节点创建了一个命名文本索引。

参数
{
  "name": "text_index_param"
}
创建单属性节点文本索引
CREATE TEXT INDEX $name FOR (n:Person) ON (n.favoriteColor)

仅在索引不存在时创建文本索引

如果不知道索引是否存在,请添加 IF NOT EXISTS 以确保其存在。

以下语句尝试为所有标记为 Person 且具有 nickname STRING 属性的节点创建一个命名文本索引。

使用 IF NOT EXISTS 创建文本索引
CREATE TEXT INDEX node_index_name IF NOT EXISTS FOR (n:Person) ON (n.nickname)

注意,如果已存在具有相同模式和类型、相同名称或两者的索引,则不会创建新索引。系统会返回一条信息性通知。

通知
`CREATE TEXT INDEX node_index_name IF NOT EXISTS FOR (e:Person) ON (e.nickname)` has no effect.
`TEXT INDEX node_text_index_nickname FOR (e:Person) ON (e.nickname)` already exists.

创建点索引

创建点索引可以使用 CREATE POINT INDEX 命令。注意,索引名称必须唯一。

点索引有支持的索引配置。

支持的谓词

点索引仅处理作用于 POINT 值的谓词。

点索引支持以下谓词

谓词 语法

属性点值。

n.prop = point({x: value, y: value})

边界框内。

point.withinBBox(n.prop, lowerLeftCorner, upperRightCorner)

距离。

point.distance(n.prop, center) < = distance

上述谓词集可以通过类型约束进行扩展。有关更多信息,请参阅 索引对查询性能的影响 → 属性类型约束

要了解有关 Cypher® 支持的空间数据类型的更多信息,请参阅关于 空间值 的页面。

示例

创建节点点索引

以下语句为所有标记为 Person 且具有 sublocation POINT 属性的节点创建了一个命名点索引。

创建单属性节点点索引
CREATE POINT INDEX node_point_index_name FOR (n:Person) ON (n.sublocation)

创建关系点索引

以下语句为所有具有关系类型 STREETPOINT 属性 intersection 的关系创建了一个命名点索引。

创建单属性关系点索引
CREATE POINT INDEX rel_point_index_name FOR ()-[r:STREET]-() ON (r.intersection)

使用参数创建点索引

以下语句使用参数作为索引名称,为所有具有关系类型 STREETPOINT 属性 coordinate 的关系创建了一个命名点索引。

参数
{
  "name": "point_index_param"
}
创建单属性关系点索引
CREATE POINT INDEX $name FOR ()-[r:STREET]-() ON (r.coordinate)

仅在索引不存在时创建点索引

如果不知道索引是否存在,请添加 IF NOT EXISTS 以确保其存在。

使用 IF NOT EXISTS 创建点索引
CREATE POINT INDEX node_point_index IF NOT EXISTS
FOR (n:Person) ON (n.sublocation)

注意,如果已存在具有相同模式和类型、相同名称或两者的索引,则不会创建新索引。系统会返回一条信息性通知。

通知
`CREATE POINT INDEX node_point_index IF NOT EXISTS FOR (e:Person) ON (e.sublocation)` has no effect.
`POINT INDEX node_point_index_name FOR (e:Person) ON (e.sublocation)` already exists.

创建指定索引配置的点索引

要使用特定的索引配置创建点索引,请在 OPTIONS 子句中使用 indexConfig 设置。有效的配置设置为:

  • spatial.cartesian.min (默认值: [-1000000.0, -1000000.0])

  • spatial.cartesian.max (默认值: [1000000.0, 1000000.0])

  • spatial.cartesian-3d.min (默认值: [-1000000.0, -1000000.0, -1000000.0])

  • spatial.cartesian-3d.max (默认值: [1000000.0, 1000000.0, 1000000.0])

  • spatial.wgs-84.min (默认值: [-180.0, -90.0])

  • spatial.wgs-84.max (默认值: [-180.0, -90.0])

  • spatial.wgs-84-3d.min (默认值: [-180.0, -90.0, -1000000.0])

  • spatial.wgs-84-3d.max (默认值: [180.0, 90.0, 1000000.0])

以下语句创建了一个点索引,指定了 spatial.cartesian.minspatial.cartesian.max 设置。

创建带有索引配置的点索引
CREATE POINT INDEX point_index_with_config
FOR (n:Label) ON (n.prop2)
OPTIONS {
  indexConfig: {
    `spatial.cartesian.min`: [-100.0, -100.0],
    `spatial.cartesian.max`: [100.0, 100.0]
  }
}

注意,未在此示例中指定的 wgs-84 和 3D 笛卡尔设置将设置为各自的默认值。

创建令牌查找索引

创建 Neo4j 数据库时会默认创建两个令牌查找索引(一个节点标签查找索引和一个关系类型查找索引)。同一时间只能存在一个节点标签查找索引和一个关系类型查找索引。

如果令牌查找索引已被删除,可以使用 CREATE LOOKUP INDEX 命令重新创建。注意,索引名称必须唯一。

令牌查找索引没有支持的索引配置。

支持的谓词

令牌查找索引默认存在,仅解决节点标签和关系类型谓词

谓词 语法 (示例)

节点标签谓词。

MATCH (n:Label)
MATCH (n)
WHERE n:Label

关系类型谓词。

MATCH ()-[r:REL]->()
MATCH ()-[r]->()
WHERE r:REL

令牌查找索引可以提高 Cypher 查询性能以及其他索引的填充速度。删除这些索引可能导致严重的性能下降。

示例

创建节点标签查找索引

以下语句为所有具有一个或多个标签的节点创建一个命名节点标签查找索引

创建节点标签查找索引
CREATE LOOKUP INDEX node_label_lookup_index FOR (n) ON EACH labels(n)

同一时间只能存在一个节点标签查找索引。

创建关系类型查找索引

以下语句为所有具有任何关系类型的关系创建一个命名关系类型查找索引。

创建关系类型查找索引
CREATE LOOKUP INDEX rel_type_lookup_index FOR ()-[r]-() ON EACH type(r)

同一时间只能存在一个关系类型查找索引。

仅在索引不存在时创建令牌查找索引

如果不知道索引是否存在,请添加 IF NOT EXISTS 以确保其存在。

使用 IF NOT EXISTS 创建节点标签查找索引
CREATE LOOKUP INDEX node_label_lookup IF NOT EXISTS FOR (n) ON EACH labels(n)

如果已存在具有相同模式和类型、相同名称或两者的索引,则不会创建新索引。系统会返回一条信息性通知。

通知
`CREATE LOOKUP INDEX node_label_lookup IF NOT EXISTS FOR (e) ON EACH labels(e)` has no effect.
`LOOKUP INDEX node_label_lookup_index FOR (e) ON EACH labels(e)` already exists.

在存在冲突索引或约束时创建索引

无法创建已存在的索引

尝试为带有 Book 标签的节点的 title 属性创建索引,但该索引已存在。

创建重复索引
CREATE INDEX bookTitleIndex FOR (book:Book) ON (book.title)

在这种情况下,由于索引已存在,因此无法创建。

GQLSTATUS 错误链

22N70: 错误: 数据异常 - 等效索引已存在。等效索引已存在: '(:Book {title})'

在创建索引时使用 IF NOT EXISTS 将不会导致错误,也不会创建新索引。

无法创建与现有索引名称相同的索引

尝试为带有 Book 标签的节点的 numberOfPages 属性创建一个命名索引,但该名称的索引已存在。现有索引的类型无关紧要。

创建重复名称的索引
CREATE INDEX indexOnBooks FOR (book:Book) ON (book.numberOfPages)

在这种情况下,由于已存在同名索引,因此无法创建该索引。

GQLSTATUS 错误链

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

在创建索引时使用 IF NOT EXISTS 将不会导致错误,也不会创建新索引。

无法在存在约束时创建索引

尝试为带有 Book 标签的节点的 isbn 属性创建一个索引,但该模式上已存在索引支持的约束。这仅适用于范围索引。

在现有索引支持的约束所在的模式上创建范围索引
CREATE INDEX bookIsbnIndex FOR (book:Book) ON (book.isbn)

在这种情况下,由于该标签和属性组合上已存在索引支持的约束,因此无法创建该索引。

GQLSTATUS 错误链

22N70: 错误: 数据异常 - 等效索引已存在。等效索引已存在: '(:Book {isbn})'

22N74: 错误: 数据异常 - 索引与现有约束冲突。索引与约束 uniqueBookIsbn 拥有的现有索引冲突。

无法创建与现有约束名称相同的索引

尝试为带有 Book 标签的节点的 numberOfPages 属性创建一个命名索引,但已存在该名称的约束。

创建与现有约束同名的索引
CREATE INDEX bookRecommendations FOR (book:Book) ON (book.recommendations)

在这种情况下,由于已存在同名约束,因此无法创建该索引。

GQLSTATUS 错误链

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