Following Relationships in Graphs
Introduction
Welcome to the fourth unit of Introduction to Graph Databases with Neo4j! We've come a long way since we started exploring graph databases. In our previous lessons, we learned how to find nodes using MATCH, retrieve specific properties with RETURN, and filter results using the WHERE clause. These skills let us ask questions about individual nodes in our ConnectHub network.
But here's the thing: what makes graph databases truly powerful isn't just the nodes themselves; it's the relationships between them. After all, social networks are fundamentally about connections. Who knows whom? Who's friends with whom? How are people connected through chains of relationships? In this lesson, we'll learn how to traverse these connections and discover the network structure that ties our users together.
Why Relationships Matter
When we think about social networks like ConnectHub, the most interesting questions aren't about isolated users. We want to know about connections: Alice's friends, mutual connections between people, or how two users might be linked through others. These are the kinds of insights that make social networks valuable.
Traditional databases struggle with these questions because they weren't designed to navigate connections efficiently. Each hop between entities requires expensive joins that slow down as the data grows. Graph databases, however, are built specifically for this purpose. Relationships are first-class citizens in the graph model, stored directly and optimized for traversal. This means we can explore networks of connections with elegant queries that remain fast even as our data scales.
The Arrow Syntax for Relationships
In Cypher, we use a visual arrow syntax to follow relationships between nodes. This syntax is intuitive and mirrors how we might draw connections on paper. The basic pattern looks like this:
The arrow shows the direction of the relationship, pointing from the start node to the end node. The relationship type appears in square brackets with a colon, similar to how we specify node labels. This visual representation makes our queries readable and self-documenting.
When we want to follow a relationship without caring about its direction, we can use a simple dash on both sides: (node1)-[:TYPE]-(node2). However, when direction matters, as it often does in social networks, we use the arrow to be specific about which way the relationship points.
Just like nodes, relationships can be given a variable name inside the square brackets, placed before the colon. This lets you reference the relationship itself in RETURN statements or filter on its properties with WHERE:
Here, r is bound to the relationship, so we can access its properties just as we would a node's. In this example, we filter on a since property stored on the relationship itself and return it alongside the friend's name.
Inline Property Syntax
So far, we've been filtering nodes using the WHERE clause:
Cypher offers a more compact alternative for matching specific property values: we can include them directly in the node pattern using curly braces:
These two queries are equivalent — they both find the user named Alice. The inline syntax {name: 'Alice'} is simply a shorthand that makes our queries more readable when we're matching specific nodes at the start of a pattern.
Finding Direct Connections
Let's start with a fundamental question: Who are Alice's friends? In our ConnectHub network, friendships are represented by FRIENDS_WITH relationships:
This query introduces several important concepts:
- We match a specific user named Alice using the inline property syntax we learned earlier.
- We then follow the
FRIENDS_WITHrelationship from Alice to other nodes. - We bind those connected nodes to the variable
friend. - Finally, we return just the names of those friends.
The arrow syntax makes it clear we're traversing from Alice outward along friendship relationships. Each friend to whom Alice is connected will appear in our results.
Understanding the Results
When we run the previous query, we get back a list of names:
This output tells us that Alice has direct friendship connections with Erin and Bob in our ConnectHub network. The simplicity of this result belies the power of what we've done: we've navigated the graph structure to discover Alice's immediate social circle.
Notice how readable this query is. Even someone unfamiliar with Cypher could likely guess what (alice)-[:FRIENDS_WITH]->(friend) means. This clarity is one of Cypher's strengths; the query language reflects the way we naturally think about connected data.
Counting Connections
Often, we don't need to see every connection; we just want to know how many there are. How many friends does Alice have? We can answer this using the count function:
The count function tallies up all the friends to whom Alice is connected. Instead of returning individual friend names, we get back a single number representing the size of Alice's social network.
This pattern is useful for analytics and summary information. We might use it to find the most connected users, identify users with few connections who might need encouragement to engage more, or track how network connectivity grows over time.
Filtering with NOT
Sometimes we want to exclude nodes or conditions from our results. The NOT keyword works with the WHERE clause to negate a condition:
This returns Alice's friends while excluding Bob. NOT can negate any condition, including comparisons, property checks, or even entire relationship patterns. You'll find it handy whenever you want to find nodes that don't satisfy a particular condition.
Friends of Friends: Multiple Hops
Here's where graph databases truly shine. What if we want to find not just Alice's friends, but friends of those friends — people who are two connections away? In a traditional database, this would require multiple complex joins. In Cypher, we simply specify the path length:
The *2 notation tells Neo4j to follow exactly two friendship relationships. This creates a path: Alice to a friend, then that friend to another person. We're discovering people in Alice's extended network who aren't directly connected to her.
Let's break down the other parts of this query:
- We use
-instead of->because friendships might go in either direction along our path. WHERE alice <> foffilters out Alice herself, since she could appear as a friend of a friend through circular paths.DISTINCTremoves duplicates because multiple paths might lead to the same person.
Variable-Length Path Results
When we execute the friends-of-friends query, we discover Alice's extended network:
Here's our ConnectHub network showing how these connections work:

In this case, both Dave and Carol are reachable through two friendship connections but aren't direct friends of Alice. Perhaps Alice knows Bob, and Bob knows Carol, or Alice knows Erin, and Erin knows Dave. The graph database has explored these paths for us, revealing how Alice is indirectly connected to both Dave and Carol.
This kind of query becomes more powerful as our network grows. We could search for paths of three, four, or more hops by changing the number after the asterisk. We could even use ranges like *1..3 to find people one to three hops away. These variable-length path queries unlock insights about network structure that would be prohibitively expensive in other database systems.
The Graph Database Advantage
What we've explored in this lesson demonstrates why graph databases excel at connected data. Each of our queries traversed the network structure naturally, following relationships from node to node. We didn't need to construct complex joins or worry about performance degrading as we added more hops.
In a relational database, finding friends of friends might require self-joining a table multiple times, creating expensive operations that slow down significantly with larger datasets. Graph databases maintain direct references between connected nodes, making traversal fast regardless of the overall database size. This architectural difference means that questions about connections, paths, and network structure become simple, performant queries rather than complex analytical challenges.
Conclusion and Next Steps
In this lesson, we've unlocked the real power of graph databases by learning to traverse relationships. We explored the intuitive arrow syntax for following connections, discovered how to find direct relationships between nodes, and learned to navigate multiple hops through our network to find extended connections.
The ability to follow relationships transforms our queries from simple lookups into explorations of network structure. Whether we're finding someone's immediate friends, counting their connections, or discovering how people are indirectly linked, Cypher's relationship syntax makes these queries natural and efficient. Now it's your turn to explore these connections! The practice exercises ahead will let you navigate through social networks, discover hidden connections, and experience firsthand how graph databases make relationship queries both simple and powerful.
