Chapter 09 · Constraints and Indexes: Range, Text, Point, Token, Full-Text, and Schema Enforcement

Uniqueness, Key, Property Existence, Property Type, and Other Constraints as Executable Model Contracts

Turn AtlasMart integrity assumptions into explicit, edition-aware database contracts.

Intermediate125–155 minutesConstraint semantics + violation labNeo4j 2026.07.1 Community · Cypher 25Last reviewed: September 2026

Learning outcomes

AtlasMart has reached the point where “the application usually writes valid data” is no longer an integrity strategy. Product identifiers arrive from imports and APIs, order-line relationships are retried, and different services can mutate the graph. The first job is to decide which rules must be executable database contracts and which remain application-level validation.

01

Distinguish labels/types used for classification from constraints used for integrity.

02

Explain uniqueness, existence, property-type and key constraints precisely.

03

State which constraint families are available in Community versus Enterprise.

04

Observe constraint state and backing indexes with SHOW CONSTRAINTS/SHOW INDEXES.

05

Prove a violation safely and separate database guarantees from remaining business invariants.

Chapter 09 baseline · reviewed 9 September 2026

The mandatory lab continues Neo4j Community 2026.07.1, database neo4j, explicit CYPHER 25 for version-sensitive examples, authentication enabled, no mandatory APOC/GDS plugin, and the AtlasMart identifiers/model established in Chapters 01–08. Neo4j 5.26.30 remains the LTS comparison line. Community currently supports node and relationship property-uniqueness constraints. Property-existence, property-type and key constraints—and Cypher 25 graph types—are Enterprise-only; Enterprise examples in this chapter are optional and are never presented as Community output.

Evidence and safety note

This generation environment does not run Neo4j or Docker. Commands were checked against current official documentation but were not executed here. Expected plans, counts, index states and scores are therefore described by invariant rather than fabricated as captured output. All disposable data uses labTag='ch09'; all disposable schema objects are named ch09_*. Never drop an index/constraint merely because its name looks similar to a lab object—verify SHOW INDEXES/SHOW CONSTRAINTS first.

1. Classification is not enforcement

A label such as :Product tells Cypher which class of node a pattern is discussing. It does not require productId to exist, be unique, or have a particular type. The same is true for relationship type :CONTAINS. Integrity begins only when a rule is enforced by a constraint or by an application transaction that tests and writes atomically.

Contract Guarantee Community 2026.07.1 Enterprise 2026.07.1 Index-backed
Property uniqueness Present values/combinations must be unique Yes · nodes + relationships Yes Yes · range index
Property existence Required property cannot be missing No Yes No
Property type Property must match declared type No Yes No
Key Properties must exist and their combination must be unique No Yes · nodes + relationships Yes · range index
Graph types Holistic element/schema contract No Yes · Cypher 25 preview Depends on contained constraints

2. Uniqueness is not existence

A uniqueness constraint only evaluates entities that contain all constrained properties. Therefore REQUIRE p.productId IS UNIQUE prevents two products from sharing the same present ID, but it does not require every :Product to have productId. That distinction is central to Community deployments: if product IDs are mandatory, Community needs an explicit validation gate in addition to the uniqueness constraint.

Cypher · mandatory Community contracts for AtlasMart
CYPHER 25CREATE CONSTRAINT product_id IF NOT EXISTSFOR (p:Product) REQUIRE p.productId IS UNIQUE;CREATE CONSTRAINT category_id IF NOT EXISTSFOR (c:Category) REQUIRE c.categoryId IS UNIQUE;CREATE CONSTRAINT order_id IF NOT EXISTSFOR (o:Order) REQUIRE o.orderId IS UNIQUE;CREATE CONSTRAINT ch09_contains_line_id_unique IF NOT EXISTSFOR ()-[r:CONTAINS]-() REQUIRE r.lineId IS UNIQUE;
Cypher · inspect the exact constraint inventory
CYPHER 25SHOW CONSTRAINTSYIELD name,type,entityType,labelsOrTypes,properties,ownedIndexRETURN name,type,entityType,labelsOrTypes,properties,ownedIndexORDER BY name;

3. Enterprise-only contracts are stronger, not interchangeable

If AtlasMart later licenses Enterprise, a key constraint can encode both existence and uniqueness in one contract, while existence/type constraints can independently require a property and its type. These commands are shown for semantics only; do not run them in the mandatory Community lab.

Optional Enterprise · examples only
CYPHER 25// Enterprise only — do not run in the Community lab.CREATE CONSTRAINT product_key IF NOT EXISTSFOR (p:Product) REQUIRE p.productId IS NODE KEY;CREATE CONSTRAINT product_name_required IF NOT EXISTSFOR (p:Product) REQUIRE p.name IS NOT NULL;CREATE CONSTRAINT product_price_type IF NOT EXISTSFOR (p:Product) REQUIRE p.price IS :: FLOAT;

4. Deliberately wrong: “the :Product label makes productId mandatory”

Create a disposable product without a business key after the uniqueness constraint exists. If the write succeeds, the evidence proves exactly why uniqueness does not imply existence.

Controlled failure of the assumption, not the database
CYPHER 25CREATE (:Product {name:'Missing-ID Probe',labTag:'ch09'});MATCH (p:Product) WHERE p.labTag='ch09' AND p.productId IS NULLRETURN count(p) AS missingProductIds,collect(p.name) AS examples;

The Community repair is to reject/quarantine rows with missing IDs before mutation and to keep the uniqueness constraint for concurrent duplicate protection. The Enterprise repair can instead promote the requirement into a key or existence contract.

5. Constraint creation is a migration event

Adding a constraint scans existing data and is atomic. It can fail because existing rows violate the rule, and uniqueness/key creation also creates a backing range index. Measure build impact on production-like data, schedule the change, and understand that dropping an index-backed constraint also drops its backing index.

Cypher · correlate constraints and owning indexes
CYPHER 25SHOW INDEXESYIELD name,type,state,entityType,labelsOrTypes,properties,owningConstraintWHERE owningConstraint IS NOT NULLRETURN name,type,state,labelsOrTypes,properties,owningConstraintORDER BY owningConstraint;

Hands-on integrity lab

Cypher · create deterministic Chapter 09 fixture
CYPHER 25MERGE (c1:Category {categoryId:'CAT-9001'}) SET c1.name='Field Electronics',c1.labTag='ch09'MERGE (c2:Category {categoryId:'CAT-9002'}) SET c2.name='Power',c2.labTag='ch09'MERGE (p1:Product {productId:'P-9001'}) SET p1.name='Trail Camera Pro',p1.description='weatherproof wildlife camera with night vision',p1.categoryCode='CAM',p1.price=189.0,p1.location=point({latitude:40.7128,longitude:-74.0060}),p1.labTag='ch09'MERGE (p2:Product {productId:'P-9002'}) SET p2.name='Trail Camera Mini',p2.description='compact wildlife camera',p2.categoryCode='CAM',p2.price=99.0,p2.location=point({latitude:40.7138,longitude:-74.0040}),p2.labTag='ch09'MERGE (p3:Product {productId:'P-9003'}) SET p3.name='Field Battery',p3.description='high capacity outdoor battery pack',p3.categoryCode='PWR',p3.price=49.0,p3.location=point({latitude:40.7100,longitude:-74.0100}),p3.labTag='ch09'MERGE (p1)-[:IN_CATEGORY]->(c1)MERGE (p2)-[:IN_CATEGORY]->(c1)MERGE (p3)-[:IN_CATEGORY]->(c2)MERGE (o:Order {orderId:'O-9001'}) SET o.labTag='ch09',o.status='PAID'MERGE (o)-[r1:CONTAINS]->(p1) SET r1.lineId='L-9001',r1.quantity=1,r1.unitPrice=189.0,r1.labTag='ch09'MERGE (o)-[r2:CONTAINS]->(p3) SET r2.lineId='L-9002',r2.quantity=2,r2.unitPrice=49.0,r2.labTag='ch09';
Cypher · prove duplicate protection
CYPHER 25// Expect this statement to fail because P-9001 already exists.CREATE (:Product {productId:'P-9001',name:'Duplicate Probe',labTag:'ch09'});
Cypher · Community-side required-ID validation
CYPHER 25MATCH (p:Product)WHERE p.labTag='ch09' AND p.productId IS NULLRETURN count(p) AS invalidProducts;// After proving the boundary, remove only the deliberate missing-ID probe.MATCH (p:Product {name:'Missing-ID Probe',labTag:'ch09'}) DETACH DELETE p;

Check your understanding

  1. Why can a uniqueness-constrained Product still lack productId?
  2. Which current constraint families are Community-safe in this lesson?
  3. What additional guarantee does a key constraint provide?
  4. Why does creating a uniqueness constraint affect index inventory?
  5. Does a constraint encode every AtlasMart business rule?
Review the answers

1. Uniqueness constrains present values; it does not imply property existence.

2. Node and relationship property-uniqueness constraints.

3. The constrained property set must exist and the value combination must be unique.

4. Neo4j creates a backing range index owned by that constraint.

5. No. Cross-entity cardinality, temporal overlap, workflow state and many other rules still need transactional/application validation.

Production judgment and next step

Constraints are correctness contracts with migration and write-path cost; use them for invariants the database can express, not as decorative schema. Keep validation queries for rules Community cannot encode and for graph-wide/business invariants that no current individual constraint expresses. Next, the chapter separates those integrity contracts from indexes whose primary purpose is query access.

Summary and next step

Uniqueness, Key, Property Existence, Property Type, and Other Constraints as Executable Model Contracts is useful only when its assumptions and observed evidence stay attached to the decision. The examples above establish a reproducible mechanism and boundary; they do not turn one lab result into a universal production rule.

Next, continue to Range, Text, Point, and Token Lookup Indexes: Supported Predicates and Workload Fit. Carry forward the verified assumptions, fixture state, version/edition boundaries, and measurements from this lesson instead of treating the next topic as an isolated recipe.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.