Indexes and constraints

This section documents the current Neo4j 2026.x calendar-versioned line — Neo4j moved from semantic to calendar versioning (YYYY.MM) in 2025, and the same line applies to the Graph Data Science library — as published at the Neo4j documentation, which is the reference these pages are written and verified against. No specific monthly patch is pinned. Some areas (Aura’s internal infrastructure, the Raft consensus implementation details, and the GDS Pregel API’s low-level internals) are linked, not documented in depth.

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production, as Neo4j iterates quickly.

This section’s bibliography lists the reference material consulted while preparing these pages.

Cypher creates and drops schema objects with the same imperative statements used elsewhere — CREATE INDEX, CREATE CONSTRAINT, SHOW INDEXES, DROP CONSTRAINT — but a Neo4j index only ever accelerates a lookup; it never enforces anything. Only a constraint rejects a write, and two of the four constraint kinds (uniqueness and node key) happen to also create a backing index as a side effect.

Index types

Six index kinds cover different value shapes and query predicates.

Six Neo4j index types — range

Range indexes

The default kind, and what plain CREATE INDEX creates: a B-tree-like structure over one or more properties of a node label or relationship type, usable for equality, range comparisons (<, , >, >=, BETWEEN), and STARTS WITH.

// https://neo4j.com/docs/cypher-manual/current/indexes/semantic-indexes/range-indexes/
CREATE INDEX person_born_range IF NOT EXISTS
FOR (p:Person) ON (p.born);

CREATE INDEX acted_in_roles_range IF NOT EXISTS
FOR ()-[r:ACTED_IN]-() ON (r.roles);

Text indexes

Backs only CONTAINS and ENDS WITH on STRING properties — predicates a range index cannot serve efficiently, since neither anchors at the start of the value.

// https://neo4j.com/docs/cypher-manual/current/indexes/semantic-indexes/text-indexes/
CREATE TEXT INDEX movie_title_text IF NOT EXISTS
FOR (m:Movie) ON (m.title);

MATCH (m:Movie)
WHERE m.title CONTAINS "Matrix"
RETURN m.title;

Point indexes

Indexes POINT (Cartesian or WGS-84) properties for distance and bounding-box queries via point.distance() or point.withinBBox().

// https://neo4j.com/docs/cypher-manual/current/indexes/semantic-indexes/point-indexes/
CREATE POINT INDEX venue_location_point IF NOT EXISTS
FOR (v:Venue) ON (v.location);

MATCH (v:Venue)
WHERE point.distance(v.location, point({latitude: 51.5, longitude: -0.12})) < 5000
RETURN v.name;

Composite indexes

A single range, text, or point index can cover more than one property of the same label or relationship type. A composite index only helps a query that supplies a predicate on every indexed property together — a predicate on just one of them falls back to a label scan.

// https://neo4j.com/docs/cypher-manual/current/indexes/semantic-indexes/range-indexes/#range-indexes-composite
CREATE INDEX person_name_born_composite IF NOT EXISTS
FOR (p:Person) ON (p.name, p.born);

MATCH (p:Person)
WHERE p.name = "Keanu Reeves" AND p.born = 1964
RETURN p;

Full-text indexes

A Lucene-backed inverted index over one or more STRING properties, queried through the db.index.fulltext.queryNodes/queryRelationships procedures rather than a WHERE predicate. It supports tokenized, relevance-scored search — word and phrase matching, fuzzy terms, boosting — and can span several labels and properties at once.

// https://neo4j.com/docs/cypher-manual/current/indexes/semantic-indexes/full-text-indexes/
CREATE FULLTEXT INDEX movie_search_fulltext IF NOT EXISTS
FOR (m:Movie|Person) ON EACH [m.title, m.name, m.tagline];

CALL db.index.fulltext.queryNodes("movie_search_fulltext", "matrix OR keanu")
YIELD node, score
RETURN node.title, node.name, score
ORDER BY score DESC;

Vector indexes

Indexes a LIST<FLOAT> embedding property for approximate nearest-neighbour similarity search — the property Neo4j’s GraphRAG and semantic-search patterns build on. vector.dimensions must match the embedding model’s output size, and vector.similarity_function is typically cosine or euclidean.

// https://neo4j.com/docs/cypher-manual/current/indexes/semantic-indexes/vector-indexes/
CREATE VECTOR INDEX movie_plot_embedding IF NOT EXISTS
FOR (m:Movie) ON (m.plotEmbedding)
OPTIONS {indexConfig: {
  `vector.dimensions`: 1536,
  `vector.similarity_function`: "cosine"
}};

Creating the index is all this page covers — for querying it, see Vector Search & GenAI, which uses the current Cypher SEARCH clause rather than the older db.index.vector.queryNodes procedure.

Constraints

A constraint is a schema rule enforced on every write, independent of whether it also happens to create an index.

Uniqueness constraints

Rejects a write that would give two nodes with the same label (or two relationships with the same type) equal values for the constrained property or property combination. It also creates a backing range index, so IF NOT EXISTS guards against redefining one that a plain index already covers.

// https://neo4j.com/docs/cypher-manual/current/constraints/managing-constraints/#create-property-uniqueness-constraints
CREATE CONSTRAINT person_email_unique IF NOT EXISTS
FOR (p:Person) REQUIRE p.email IS UNIQUE;

Property existence constraints

Rejects a write that would leave the constrained property missing on a node with the given label, or on a relationship of the given type. Community Edition supports existence constraints only on relationship properties; node property existence constraints require Enterprise Edition.

// https://neo4j.com/docs/cypher-manual/current/constraints/managing-constraints/#create-property-existence-constraints
CREATE CONSTRAINT person_name_exists IF NOT EXISTS
FOR (p:Person) REQUIRE p.name IS NOT NULL;

CREATE CONSTRAINT acted_in_roles_exists IF NOT EXISTS
FOR ()-[r:ACTED_IN]-() REQUIRE r.roles IS NOT NULL;

Node key constraints

The multi-property, Enterprise-only combination of uniqueness and existence: every node with the given label must carry all of the listed properties, and no two such nodes may share the same combination of values — the closest Cypher equivalent of a relational composite primary key.

// https://neo4j.com/docs/cypher-manual/current/constraints/managing-constraints/#create-node-key-constraints
CREATE CONSTRAINT order_line_key IF NOT EXISTS
FOR (l:OrderLine) REQUIRE (l.orderId, l.lineNumber) IS NODE KEY;

Relationship key and property type constraints

Neo4j 5 added the relationship-side counterpart of a node key — IS RELATIONSHIP KEY — plus IS TYPED constraints that pin a property to a single Cypher type, both Enterprise-only.

// https://neo4j.com/docs/cypher-manual/current/constraints/managing-constraints/#create-relationship-key-constraints
CREATE CONSTRAINT rated_key IF NOT EXISTS
FOR ()-[r:RATED]-() REQUIRE (r.userId, r.movieId) IS RELATIONSHIP KEY;

// https://neo4j.com/docs/cypher-manual/current/constraints/managing-constraints/#create-property-type-constraints
CREATE CONSTRAINT person_born_typed IF NOT EXISTS
FOR (p:Person) REQUIRE p.born IS :: INTEGER;

Inspecting and removing schema objects

SHOW INDEXES and SHOW CONSTRAINTS list every schema object with its name, type, entity, and properties — including the implicit indexes a uniqueness or node-key constraint created. Both accept YIELD to project specific columns, and a WHERE clause to filter.

// https://neo4j.com/docs/cypher-manual/current/indexes/syntax/#indexes-list-indexes
SHOW INDEXES YIELD name, type, entityType, labelsOrTypes, properties, state;

// https://neo4j.com/docs/cypher-manual/current/constraints/managing-constraints/#constraints-list-constraints
SHOW CONSTRAINTS YIELD name, type, entityType, labelsOrTypes, properties;

Drop either by the name shown in those results — IF EXISTS makes the drop idempotent, and dropping a uniqueness or node-key constraint also drops its backing index.

// https://neo4j.com/docs/cypher-manual/current/indexes/syntax/#indexes-drop-index
DROP INDEX person_born_range IF EXISTS;

// https://neo4j.com/docs/cypher-manual/current/constraints/managing-constraints/#constraints-drop-constraint
DROP CONSTRAINT person_email_unique IF EXISTS;
  • Indexes — the full index reference this page summarizes.

  • Semantic indexes — the range, text, and point index kinds in depth.

  • Vector indexes — dimensions, similarity functions, and querying an embedding index.

  • Elasticsearch Reference — an indexing model built the opposite way round: every document is indexed by default rather than opted in per property.

  • MongoDB Reference — secondary indexes over a document collection, for contrast with indexing a property graph.