Hello Graph: Friend-of-Friend

Build a 6-person social graph and find friends-of-friends with a single Cypher pattern match

All recipes· graph· 3 minutesbeginnercypher

Hello Graph: Friend-of-Friend

Objective

Build a small social network and answer "who are my friends-of-friends?" — the question that kicked off graph-database adoption at LinkedIn and Facebook. In SQL this requires a self-join on the friendship table for every extra hop. In Cypher it is a single pattern of length two.

Step 1: Create the graph

// People
MERGE (sarah:Person {name: "Sarah Chen"})
MERGE (raj:Person {name: "Raj Patel"})
MERGE (mia:Person {name: "Mia Rossi"})
MERGE (leo:Person {name: "Leo Park"})
MERGE (eli:Person {name: "Eli Tanaka"})
MERGE (zoe:Person {name: "Zoe Williams"})

// Direct friendships (undirected, modeled as two-way)
MERGE (sarah)-[:FRIENDS_WITH]->(raj)
MERGE (sarah)-[:FRIENDS_WITH]->(mia)
MERGE (raj)-[:FRIENDS_WITH]->(leo)
MERGE (raj)-[:FRIENDS_WITH]->(eli)
MERGE (mia)-[:FRIENDS_WITH]->(zoe)
MERGE (leo)-[:FRIENDS_WITH]->(zoe)
MERGE (eli)-[:FRIENDS_WITH]->(zoe);

Step 2: Find Sarah's friends-of-friends

// Pattern: Sarah --FRIENDS_WITH--> friend --FRIENDS_WITH--> fof
// Exclude Sarah herself and anyone she's already friends with.
MATCH (sarah:Person {name: "Sarah Chen"})-[:FRIENDS_WITH]->(friend)-[:FRIENDS_WITH]->(fof)
WHERE fof <> sarah
  AND NOT (sarah)-[:FRIENDS_WITH]->(fof)
RETURN fof.name AS suggestion, count(DISTINCT friend) AS mutual_friends
ORDER BY mutual_friends DESC, suggestion;

What's happening

  • The two-hop pattern (sarah)-->(friend)-->(fof) traverses the graph natively — no joins.
  • count(DISTINCT friend) ranks suggestions by how many mutual friends connect them.
  • The NOT (sarah)-->(fof) predicate excludes existing direct friendships in one anti-pattern check.
  • In SQL, this would require two self-joins on a friendships table plus a NOT EXISTS subquery.
  • Cypher's pattern syntax reads like the question itself — a key reason graphs feel intuitive.

Try this next

MATCH (p:Person {name: "Raj Patel"})-[:FRIENDS_WITH*1..2]-(other)
WHERE p <> other
RETURN DISTINCT other.name;
MATCH (a:Person)-[:FRIENDS_WITH]-(b:Person)
RETURN a.name AS person, count(b) AS degree
ORDER BY degree DESC;
MATCH path = shortestPath((a:Person {name: "Sarah Chen"})-[:FRIENDS_WITH*]-(b:Person {name: "Zoe Williams"}))
RETURN [n IN nodes(path) | n.name] AS hops, length(path) AS distance;

Tags

graphcyphersocialbeginner

Run this on your own machine

Install SynapCores Community Edition free, paste the SQL or Cypher above into the bundled web UI, and watch it run.

Download Free CE