Chapter 04 · Advanced Pattern Matching: Variable Length, OPTIONAL MATCH, Paths, Quantified Patterns, and Shortest Paths
Path Values, Nodes/Relationships Functions, Path Predicates, Uniqueness, and Cycle Awareness
Make the exact matched path observable, then reason precisely about cycles and which elements may repeat under each match/path mode.
Learning outcomes
When a query returns a path, the path is a value—not just a visualization. AtlasMart can inspect its nodes, relationships, hop length and properties, then enforce path-level predicates. Those tools are also how you prove what “cycle” and “uniqueness” mean in the concrete fixture.
Bind a path variable and inspect nodes(), relationships(), length() and relationship properties.
Distinguish revisiting a node from reusing the same relationship.
Explain Cypher default relationship uniqueness and current explicit DIFFERENT RELATIONSHIPS semantics.
Use bounded REPEATABLE ELEMENTS/ACYCLIC examples only with the Cypher-version caveats they require.
Write path predicates that test business properties without hiding combinatorial cost.
Continue Chapters 01–03 with Neo4j Community
2026.07.1, database neo4j, explicit
CYPHER 25 in version-sensitive examples, local
container atlasmart-neo4j, Bolt
127.0.0.1:7687, HTTP 127.0.0.1:7474,
and constraint-backed AtlasMart domain identifiers. Chapter 04
adds a small synthetic operational handoff subgraph on
existing Supplier/Category/Store concepts; it is intentionally
isolated for path-mechanics exercises and does not replace the
transactional relationships modeled earlier.
Neo4j 2026.07.1 is the current 2026 release used
by this course snapshot; 5.26.30 remains the
current 5.26 LTS comparison line. The current manual covers
Cypher 25; Cypher 5 is frozen. Quantified path
patterns/relationships date from Neo4j 5.9, while explicit
Cypher 25 path modes such as ACYCLIC arrived
later and have version-sensitive combination rules. Commands
here were checked against current documentation but could not
be executed in this generation environment, so expected output
is described by deterministic invariants rather than
fabricated captures.
1. A path variable exposes the exact matched sequence
CYPHER 25CREATE CONSTRAINT supplier_id IF NOT EXISTS FOR (s:Supplier) REQUIRE s.supplierId IS UNIQUE;CREATE CONSTRAINT category_id IF NOT EXISTS FOR (c:Category) REQUIRE c.categoryId IS UNIQUE;CREATE CONSTRAINT store_id IF NOT EXISTS FOR (s:Store) REQUIRE s.storeId IS UNIQUE;CREATE CONSTRAINT ops_point_id IF NOT EXISTS FOR (n:OpsPoint) REQUIRE n.pointId IS UNIQUE;MERGE (s1:Supplier {supplierId:'SUP-3001'}) SET s1:OpsPoint, s1.pointId='OP-SUP-1', s1.name='Northwind Optics';MERGE (s2:Supplier {supplierId:'SUP-3002'}) SET s2:OpsPoint, s2.pointId='OP-SUP-2', s2.name='Audio Forge';MERGE (c1:Category {categoryId:'CAT-CAMERAS'}) SET c1:OpsPoint, c1.pointId='OP-CAT-CAM', c1.name='Cameras';MERGE (c2:Category {categoryId:'CAT-AUDIO'}) SET c2:OpsPoint, c2.pointId='OP-CAT-AUD', c2.name='Audio';MERGE (st1:Store {storeId:'ST-001'}) SET st1:OpsPoint, st1.pointId='OP-ST-1', st1.name='Central', st1.region='west';MERGE (st2:Store {storeId:'ST-002'}) SET st2:OpsPoint, st2.pointId='OP-ST-2', st2.name='Harbor', st2.region='east';MERGE (st3:Store {storeId:'ST-003'}) SET st3:OpsPoint, st3.pointId='OP-ST-3', st3.name='Airport', st3.region='north';MATCH (s1:OpsPoint {pointId:'OP-SUP-1'}), (s2:OpsPoint {pointId:'OP-SUP-2'}), (c1:OpsPoint {pointId:'OP-CAT-CAM'}), (c2:OpsPoint {pointId:'OP-CAT-AUD'}), (st1:OpsPoint {pointId:'OP-ST-1'}), (st2:OpsPoint {pointId:'OP-ST-2'}), (st3:OpsPoint {pointId:'OP-ST-3'})MERGE (s1)-[:HANDOFF_TO {routeId:'R01', minutes:30, active:true}]->(st1)MERGE (s1)-[:HANDOFF_TO {routeId:'R02', minutes:10, active:true}]->(c1)MERGE (c1)-[:HANDOFF_TO {routeId:'R03', minutes:8, active:true}]->(st1)MERGE (c1)-[:HANDOFF_TO {routeId:'R04', minutes:5, active:true}]->(c2)MERGE (st1)-[:HANDOFF_TO {routeId:'R05', minutes:12, active:true}]->(s2)MERGE (st1)-[:HANDOFF_TO {routeId:'R06', minutes:11, active:false}]->(c2)MERGE (s2)-[:HANDOFF_TO {routeId:'R07', minutes:9, active:true}]->(c2)MERGE (s2)-[:HANDOFF_TO {routeId:'R08', minutes:6, active:true}]->(st2)MERGE (c2)-[:HANDOFF_TO {routeId:'R09', minutes:7, active:true}]->(st2)MERGE (st2)-[:HANDOFF_TO {routeId:'R10', minutes:14, active:true}]->(s1)MERGE (st2)-[:HANDOFF_TO {routeId:'R11', minutes:4, active:true}]->(st3)MERGE (st3)-[:HANDOFF_TO {routeId:'R12', minutes:13, active:true}]->(c1);
CYPHER 25MATCH p=(:OpsPoint {pointId:'OP-SUP-1'})-[:HANDOFF_TO]->{1,4}(:Store:OpsPoint {storeId:'ST-002'})RETURN length(p) AS hops, [n IN nodes(p) | n.pointId] AS pointIds, [r IN relationships(p) | r.routeId] AS routeIds, reduce(total=0, r IN relationships(p) | total + r.minutes) AS minutesORDER BY hops, minutes, pointIds;
nodes(p) and relationships(p) preserve
path order. length(p) counts relationships, not
nodes. The reduction computes a path property for inspection; it
does not make the pattern selector weighted.
2. Nodes may repeat under default matching; relationships may not
CYPHER 25MATCH p=(s:OpsPoint {pointId:'OP-SUP-1'})-[:HANDOFF_TO]->{2,7}(s)RETURN length(p) AS hops, [n IN nodes(p) | n.pointId] AS points, [r IN relationships(p) | r.routeId] AS routesORDER BY hopsLIMIT 10;
The fixture contains a directed cycle back to
OP-SUP-1. Seeing the start node again is legal.
Under default match semantics, however, the same relationship is
not traversed twice within one matched result. Current Cypher 25
can spell that default match mode explicitly as
DIFFERENT RELATIONSHIPS.
CYPHER 25MATCH DIFFERENT RELATIONSHIPS p=(s:OpsPoint {pointId:'OP-SUP-1'})-[:HANDOFF_TO]->{1,6}(t:OpsPoint)RETURN count(p) AS boundedPaths;
3. REPEATABLE ELEMENTS changes the search space
REPEATABLE ELEMENTS is a Cypher 25 match mode
that permits relationships to be revisited. On a cyclic graph,
removing a finite bound can make the candidate space
operationally dangerous.
CYPHER 25MATCH REPEATABLE ELEMENTS p=(s:OpsPoint {pointId:'OP-SUP-1'})-[:HANDOFF_TO]->{1,6}(t:OpsPoint)RETURN count(p) AS repeatableBoundedPaths;
This is a semantic tool, not a performance trick. Use it only when repeated elements are part of the domain question, such as modeling walks rather than trails.
4. ACYCLIC is a current path mode, not timeless Cypher syntax
Cypher 25 added explicit path modes in the 2026 line.
ACYCLIC prevents a node from repeating within the
path. Its availability and combination with restrictive
selectors changed across 2026 patches, so version-pin any lesson
or production query that uses it.
CYPHER 25MATCH p=ACYCLIC (:OpsPoint {pointId:'OP-SUP-1'})-[:HANDOFF_TO]->{1,6}(t:Store:OpsPoint)RETURN t.storeId, length(p) AS hops, [n IN nodes(p) | n.pointId] AS pointsORDER BY hops, t.storeId;
Do not backport this syntax mentally to Cypher 5. The stable concept is the requirement “no repeated nodes”; the exact syntax is release-sensitive.
5. Path predicates express domain rules, but they do not erase path enumeration
CYPHER 25MATCH p=(:OpsPoint {pointId:$source})-[:HANDOFF_TO]->{1,5}(target:Store:OpsPoint)WHERE all(r IN relationships(p) WHERE r.active=true) AND reduce(total=0, r IN relationships(p) | total+r.minutes) <= $budgetMinutesRETURN target.storeId, length(p) AS hops, [r IN relationships(p) | r.routeId] AS routesORDER BY hops, target.storeId;
For large search spaces, prefer predicates that can prune during the quantified pattern rather than only a final path-level predicate. Production judgment means separating semantic correctness from search strategy. The next lesson uses that distinction to show why hop-shortest and cost-shortest are different questions.
Check your understanding
- What does length(p) count?
- Can a node repeat in a default matched path?
- Can the same relationship repeat under the default match behavior?
- What does REPEATABLE ELEMENTS change?
- Why is ACYCLIC treated as version-sensitive in this course?
Review the answers
1. Relationships/hops, not nodes.
2. Yes, a node may be revisited.
3. No, not within a default matched result.
4. It allows elements, including relationships, to be revisited, so the path search space changes materially.
5. It is a newer Cypher 25 path mode whose availability/combination rules evolved across 2026 releases.
Summary and next step
Path Values, Nodes/Relationships Functions, Path Predicates, Uniqueness, and Cycle Awareness 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 Shortest-Path Queries, Weighted vs Unweighted Reasoning, and When to Use Graph Data Science Instead. 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
- Current Neo4j versions — Official current-release and 5.26 LTS patch snapshot.
- Cypher Manual introduction — Current Cypher 25 baseline and Cypher 5 compatibility framing.
- Patterns — Current graph/path matching overview, including shortest paths and match/path modes.
- Variable-length paths — Quantified path patterns, quantified relationships, group variables and inline predicates.
- Variable-length path reference — Formal syntax and rules for quantified and legacy variable-length patterns.
- Path-pattern reference — Path values, path-pattern composition and matching rules.
- Unique relationship paths — Default relationship-uniqueness behavior and DIFFERENT RELATIONSHIPS semantics.
- Match modes and path modes — Current Cypher 25 WALK/TRAIL/ACYCLIC and match-mode compatibility rules.
- OPTIONAL MATCH — Outer-row preservation and null introduction when a pattern is absent.
- WHERE — WHERE as a subclause of MATCH/OPTIONAL MATCH and its pattern-scoping consequences.
- Path functions — nodes(), relationships(), length()/path_length() and path-related list/predicate functions.
- Shortest paths — Current SHORTEST/ALL SHORTEST path selector semantics.
- Query plans and operators — Execution-plan operators and row/db-hit/memory evidence.
- GDS graph algorithms — Graph Data Science algorithm families including path finding.
- GDS Dijkstra source-target — Weighted positive-edge shortest-path algorithm for projected GDS graphs.