Direction, path variables, and variable-length patterns
Relationships in Neo4j are stored with a direction. Pattern arrows must respect that storage unless you deliberately write an undirected pattern. Directed patterns answer oriented questions (“who directed this film?”). Undirected patterns answer connectivity questions where orientation is irrelevant (“are these people linked through shared films in either modeled direction?”). Mixing them up is the number-one cause of empty path results for intermediate learners.
A path variable captures an entire matched walk: nodes and relationships together.
Write MATCH p = (a)-[:ACTED_IN]->(m)<-[:ACTED_IN]-(b) and you can
RETURN p, length(p),
nodes(p), or relationships(p).
Paths are values—great for visualization and for feeding path functions.
Variable-length relationship patterns expand a type repeatedly:
-[:ACTED_IN*1..2]- means one or two ACTED_IN hops in an undirected sense
when written without arrows (or follow the arrows you draw). Bounds are not optional in careful systems
work: unbounded * can explode on dense social graphs. Always prefer an
upper bound that matches the business question (for example “within two collaborations”).
When paths shine: recommendations, impact analysis, fraud rings, dependency depth, and any UI that draws a route. Prefer fixed two-hop patterns when the shape is known; use variable length when the hop count is a range; use shortest-path functions when the goal is a minimum route between two fixed ends.
MATCH p = (a:Person {name: "Tom Hanks"})-[:ACTED_IN*1..2]-(b:Person)
WHERE a <> b
// path variable p captures the walk; length(p) is hop count
RETURN b.name AS other, length(p) AS hops
ORDER BY hops, other
LIMIT 10