Syntax

This page contains the syntax for creating, listing, and dropping the indexes available in Neo4j. It also contains the signatures for the procedures necessary to call in order to use full-text and vector indexes.

More details about the syntax can be found in the Operations Manual → Cypher® syntax for administration commands.

CREATE INDEX

The general structure of the CREATE INDEX command is:

CREATE [index_type] INDEX [index_name] [IF NOT EXISTS]
FOR {node_pattern | relationship_pattern}
ON property_or_token_lookup_pattern
[OPTIONS “{“ option: value[, …] “}”]

The CREATE … INDEX … command is optionally idempotent. This means that its default behavior is to throw an error if an attempt is made to create an index with the same name twice. With IF NOT EXISTS, no error is thrown and nothing happens should an index with the same name or same schema and index type already exist (it may still throw an error if conflicting constraints exist, such as constraints with the same name or with the same schema and backing index). As of Neo4j 5.17, an informational notification is instead returned showing the existing index which blocks the creation.

The index name must be unique among both indexes and constraints. A random name will be assigned if no name is explicitly given when an index is created.

Index configuration settings can be specified using the OPTIONS clause. However, not all indexes have available configuration settings. In those cases, nothing needs to be specified and the OPTIONS map should be omitted from the query.

Creating an index requires the CREATE INDEX privilege.

Range indexes

Range indexes have no supported index configuration. The OPTIONS map has, therefore, been omitted from the syntax below.

Create a range index for a node label, either on a single property or composite
CREATE [RANGE] INDEX [index_name] [IF NOT EXISTS]
FOR (n:LabelName)
ON (n.propertyName_1[,
    n.propertyName_2,
    ...
    n.propertyName_n])
Create a range index for a relationship type, either on a single property or composite
CREATE [RANGE] INDEX [index_name] [IF NOT EXISTS]
FOR ()-”[“r:TYPE_NAME”]”-()
ON (r.propertyName_1[,
    r.propertyName_2,
    ...
    r.propertyName_n])

Text indexes

Text indexes have no supported index configuration. The OPTIONS map has, therefore, been omitted from the syntax below.

Create a text index for a node label on a single property
CREATE TEXT INDEX [index_name] [IF NOT EXISTS]
FOR (n:LabelName)
ON (n.propertyName_1)
Create a text index for a relationship type on a single property
CREATE TEXT INDEX [index_name] [IF NOT EXISTS]
FOR ()-”[“r:TYPE_NAME”]”-()
ON (r.propertyName_1)
It is not possible to create composite text indexes on multiple properties.

Point indexes

Create a point index for a node label on a single property
CREATE POINT INDEX [index_name] [IF NOT EXISTS]
FOR (n:LabelName)
ON (n.propertyName_1)
[OPTIONS “{“ option: value[, …] “}”]
Create a point index for a relationship type on a single property
CREATE POINT INDEX [index_name] [IF NOT EXISTS]
FOR ()-”[“r:TYPE_NAME”]”-()
ON (r.propertyName_1)
[OPTIONS “{“ option: value[, …] “}”]

The following settings can be specified for point indexes:

  • spatial.cartesian.min

  • spatial.cartesian.max

  • spatial.cartesian-3d.min

  • spatial.cartesian-3d.max

  • spatial.wgs-84.min

  • spatial.wgs-84.max

  • spatial.wgs-84-3d.min

  • spatial.wgs-84-3d.max

It is not possible to create composite point indexes on multiple properties.

Token lookup indexes

Token lookup indexes have no supported index configuration. The OPTIONS map has, therefore, been omitted from the syntax below.

Create a node label lookup index
CREATE LOOKUP INDEX [index name] [IF NOT EXISTS]
FOR (n)
ON EACH labels(n)
Create a relationship type lookup index
CREATE LOOKUP INDEX [index name] [IF NOT EXISTS]
FOR ()-”[“r”]”-()
ON [EACH] type(r)

Two token lookup indexes are present by default when creating a Neo4j database, and only one node label lookup index and one relationship type lookup index can exist at the same time.

Full-text indexes

Create a full-text index for one or more node labels, either on a single property or multiple properties
CREATE FULLTEXT INDEX [index_name] [IF NOT EXISTS]
FOR (n:LabelName[“|” …])
ON EACH “[“ n.propertyName[, ...] “]”
[OPTIONS “{“ option: value[, …] “}”]
Create a full-text index for one or more relationship types, either on a single property or multiple properties
CREATE FULLTEXT INDEX [index_name] [IF NOT EXISTS]
FOR ()-”[“r:TYPE_NAME[“|” ...]”]”-()
ON EACH “[“ r.propertyName[, ...] “]”
[OPTIONS “{“ option: value[, …] “}”]

The following settings can be specified for full-text indexes:

  • fulltext.analyzer - specifies what analyzer to use (the db.index.fulltext.listAvailableAnalyzers procedure lists what analyzers are available).

  • fulltext.eventually_consistent - specifies whether a full-text index is eventually consistent. If set to true, it will ensure that updates from committing transactions are applied in a background thread.

Vector indexes

Create a vector index for a node label on a single property Introduced in 5.15
CREATE VECTOR INDEX [index_name] [IF NOT EXISTS]
FOR (n:LabelName)
ON (n.propertyName)
[OPTIONS “{“ option: value[, …] “}”]
Create a vector index for a relationship type on a single property Introduced in 5.18
CREATE VECTOR INDEX [index_name] [IF NOT EXISTS]
FOR ()-”[“r:TYPE_NAME”]”-()
ON (r.propertyName)
[OPTIONS “{“ option: value[, …] “}”]

For a full list of all vector index settings, see Vector index configuration settings. Note that the OPTIONS clause was mandatory prior to Neo4j 5.23 because it was necessary to configure the vector.dimensions and vector.similarity_function settings when creating a vector index.

OPTIONS {
  indexConfig: {
    `vector.dimensions`: $dimension,
    `vector.similarity_function`: $similarityFunction
  }
}
It is not possible to create composite vector indexes on multiple properties.

SHOW INDEX

Listing indexes requires the SHOW INDEX privilege.
List indexes in the database (either all or filtered on index type)
SHOW [ALL | FULLTEXT | LOOKUP | POINT | RANGE | TEXT | VECTOR] INDEX[ES]
[YIELD { * | field[,...] } [ORDER BY field[,...]] [SKIP n] [LIMIT n]]
[WHERE expression]
[RETURN field[, ...] [ORDER BY field[, ...]] [SKIP n] [LIMIT n]]

When using the RETURN clause, the YIELD clause is mandatory.

Query semantic indexes

Neo4j’s semantic indexes are not used automatically in Cypher queries. To use them, specific procedures must be called. Their signatures can be seen below.

Full-text indexes

Query full-text index on nodes: db.index.fulltext.queryNodes
CALL db.index.fulltext.queryNodes(indexName :: STRING, queryString :: STRING, options = {} :: MAP)
Query full-text index on relationships: db.index.fulltext.queryRelationships
CALL db.index.fulltext.queryRelationships(indexName :: STRING, queryString :: STRING, options = {} :: MAP)

The valid key: value pairs for the options map are:

  • skip: <number> — skip the top N results.

  • limit: <number> — limit the number of results returned.

  • analyzer: <string> — use the specified analyzer as a search analyzer for this query.

The options map and all of the keys are optional.

For more information, see Full-text indexes - Query full-text indexes.

Vector indexes

Query vector-text index on nodes: db.index.vector.queryNodes Introduced 5.11
CALL db.index.vector.queryNodes(indexName :: STRING, numberOfNearestNeighbours :: INTEGER, query :: LIST<INTEGER | FLOAT>)
Query vector-text index on relationships: db.index.vector.queryRelationships Introduced 5.18
CALL db.index.vector.queryRelationships(indexName :: STRING, numberOfNearestNeighbours :: INTEGER, query :: LIST<INTEGER | FLOAT>)

The numberOfNearestNeighbours refers to the number of nearest neighbors to return as the neighborhood. The query vector refers to the LIST<FLOAT> in which to search for the neighborhood.

For more information, see Vector indexes - Query vector indexes.

DROP INDEX

The DROP INDEX command can drop indexes of all types using their name. The name of the index can be found using the SHOW INDEXES command, given in the output column name.

The DROP INDEX command is optionally idempotent. This means that its default behavior is to throw an error if an attempt is made to drop the same index twice. With IF EXISTS, no error is thrown and nothing happens should the index not exist. As of Neo4j 5.17, an informational notification is instead returned detailing that the index does not exist.

Dropping indexes requires the DROP INDEX privilege.
Drop an index of any index type
DROP INDEX index_name [IF EXISTS]