Skip to content

SynapCores / Recipe

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
Instance: localhost:8080

Opens your running SynapCores (Hello Graph: Friend-of-Friend will be staged for a preview — nothing runs until you click Run). No instance yet? Install free in ~30s.

Share

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