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

Full-Text Indexes, Analyzers, Eventual Consistency Options, and Query Procedures

Build lexical AtlasMart retrieval with explicit analyzer, score and freshness contracts.

Advanced125–155 minutesFull-text relevance/freshness labNeo4j 2026.07.1 Community · Cypher 25Last reviewed: September 2026

Learning outcomes

AtlasMart product search now needs lexical relevance rather than only exact/range predicates. Full-text indexes are Lucene-backed semantic indexes: they tokenize string content, return query scores, support analyzers, and must be queried explicitly. Their score and freshness contracts differ from normal search-performance indexes.

01

Create node and relationship full-text indexes over one or more labels/types/properties.

02

Explain analyzers, tokenization and Lucene query behavior.

03

Distinguish synchronous index updates from the eventual-consistency option.

04

Query full-text indexes explicitly and interpret scores as query-specific relevance evidence.

05

Prove freshness when eventual consistency is enabled instead of assuming immediate visibility.

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. Full-text is not a bigger text index

A text index accelerates particular string predicates in ordinary MATCH/WHERE planning. A full-text index tokenizes the content of STRING or LIST<STRING> properties and is queried explicitly through db.index.fulltext.queryNodes() or queryRelationships(). It can cover multiple labels/types and multiple properties.

Cypher · create a lexical AtlasMart index
CYPHER 25CREATE FULLTEXT INDEX ch09_content_fulltext IF NOT EXISTSFOR (n:Product) ON EACH [n.name,n.description]OPTIONS {indexConfig:{`fulltext.analyzer`:'english'}};CALL db.awaitIndex('ch09_content_fulltext',300);
Cypher · explicit full-text query
CYPHER 25CALL db.index.fulltext.queryNodes('ch09_content_fulltext','camera')YIELD node,scoreRETURN node.productId AS productId,node.name AS name,scoreORDER BY score DESC;

2. Analyzer choice changes the token stream

The analyzer controls tokenization, normalization and stop-word behavior. The current default is standard-no-stop-words; this lab chooses english deliberately. Use the built-in procedure to inspect what is actually available in the running release before freezing a language-specific configuration.

Cypher · inspect analyzers
CYPHER 25CALL db.index.fulltext.listAvailableAnalyzers()YIELD analyzer,description,stopwordsRETURN analyzer,description,stopwordsORDER BY analyzer;

3. Scores are evidence for one retrieval request

The returned score is produced by the full-text search engine for the current index/query. It is not a normalized probability and should not be compared as if a score of 0.8 from one query/index has the same meaning as 0.8 from another. Evaluate ranking with judged queries and application relevance metrics.

Cypher · query with procedure options
CYPHER 25CALL db.index.fulltext.queryNodes(  'ch09_content_fulltext',  'camera OR battery',  {limit:10}) YIELD node,scoreRETURN node.productId,node.name,scoreORDER BY score DESC;

4. Eventual-consistency mode moves index updates off the commit path

By default, full-text updates participate in normal synchronous index update behavior. Setting fulltext.eventually_consistent=true applies changes asynchronously in a background thread. That can reduce commit-path work, but a just-committed value may not be immediately searchable. Freshness becomes an explicit service-level contract.

Cypher · optional asynchronous review index
CYPHER 25CREATE FULLTEXT INDEX ch09_review_async_fulltext IF NOT EXISTSFOR (r:Review) ON EACH [r.text]OPTIONS {indexConfig:{`fulltext.analyzer`:'english',`fulltext.eventually_consistent`:true}};CALL db.awaitIndex('ch09_review_async_fulltext',300);CREATE (:Review {reviewId:'R-9001',text:'Camera battery life is excellent',labTag:'ch09'});CALL db.index.fulltext.awaitEventuallyConsistentIndexRefresh();CALL db.index.fulltext.queryNodes('ch09_review_async_fulltext','excellent')YIELD node,scoreRETURN node.reviewId,node.text,score;

5. Deliberately wrong: assert immediate search freshness on an eventual index

The write transaction can commit successfully while the asynchronous index update is still queued. A test that performs an immediate query and treats a miss as data loss is testing the wrong contract. For deterministic lab assertions, call the refresh-wait procedure; for production, define tolerated freshness and monitor queue/backlog behavior rather than forcing synchronous waits into every request.

Check your understanding

  1. Why is a full-text index not automatically used by MATCH?
  2. What property types can current full-text indexes include?
  3. What does an analyzer change?
  4. Does a higher score mean “90% correct”?
  5. How do you make an eventual-consistency lab assertion deterministic?
Review the answers

1. It is a semantic index queried explicitly through full-text procedures.

2. STRING and LIST values.

3. How indexed/query text is tokenized/normalized and which stop-word/stemming behavior applies.

4. No. It is query/index-specific relevance evidence, not a probability.

5. Wait with db.index.fulltext.awaitEventuallyConsistentIndexRefresh() before asserting the new content is searchable.

Summary and next step

Full-text indexing is an explicit retrieval subsystem with its own analyzer, score and freshness contracts. The final lesson audits the whole schema and removes structures that have no demonstrated workload value.

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.