One story, three tellings, one graph: Homer's Odyssey (Emily Wilson's translation), EPIC: The Musical, and Christopher Nolan's The Odyssey (2026) - every character, god, monster, place, song, saga, and actor, modelled as a Neo4j knowledge graph.
Built as a learning project and written up in full on the GraphAcademy blog: The Odyssey in a Graph Database.
Two CSV files. The whole dataset.
| column | what it is |
|---|---|
name |
Unique name (see "quirks" below) |
type |
One of: Hero, Mortal, Deity, Monster, Animal, Place, Saga, Song, Actor |
description |
What/who this is |
notes |
Extras: EPIC musical motifs, "Homer only" markers, casting notes |
source |
Where this row's facts came from |
130 nodes: 3 Heroes, 17 Mortals, 13 Deities, 5 Monsters, 1 very good dog, 14 Places, 9 Sagas, 40 Songs, 28 Actors.
| column | what it is |
|---|---|
from, to |
Node names (must match nodes.csv) |
type |
Relationship type, e.g. BLINDS, BETRAYS, PLAYS, TRAVELS_TO |
detail |
The story behind the arrow |
source |
Where this claim comes from |
235 relationships across 28 types - family (CHILD_OF, MARRIED_TO), drama (BLINDS, CURSES, BETRAYS, KILLS), geography (TRAVELS_TO, LIVES_IN), the musical (PART_OF, FEATURES), and casting (PLAYS, with a detail marking film vs musical).
- Create a free instance at console.neo4j.io
- In the Query tab, set the uniqueness rule:
CREATE CONSTRAINT entity_name IF NOT EXISTS
FOR (n:Entity) REQUIRE n.name IS UNIQUE- Load the nodes:
LOAD CSV WITH HEADERS FROM 'https://raw.githubusercontent.com/Kemi-Elizabeth/odyssey_graph/main/nodes.csv' AS row
MERGE (n:Entity {name: row.name})
SET n:$(row.type),
n.description = row.description,
n.notes = row.notes,
n.source = row.source- Load the relationships:
LOAD CSV WITH HEADERS FROM 'https://raw.githubusercontent.com/Kemi-Elizabeth/odyssey_graph/main/relationships.csv' AS row
MATCH (a:Entity {name: row.from})
MATCH (b:Entity {name: row.to})
MERGE (a)-[r:$(row.type)]->(b)
SET r.detail = row.detail,
r.source = row.source- Drop the scaffolding (so Bloom colour-codes by real type):
DROP CONSTRAINT entity_nameMATCH (n) REMOVE n:Entity- Verify: you should have exactly 130 nodes and 235 relationships:
MATCH (n) OPTIONAL MATCH (n)-[r]->()
RETURN count(DISTINCT n) AS nodes, count(r) AS relationshipsRe-running the import after step 5 will create duplicates (the
MERGEmatches on theEntitylabel you just removed). If you need to rebuild, useMATCH (n) DETACH DELETE nand repeat from step 2.
Download odyssey_data_import_neo4j.zip, then in Aura go to Import → ⋯ → Open model (with data), choose the zip, and hit Run import - the full graph builds itself.
And if you want it to look like the blog post too: in Bloom → Perspectives → Import, choose odyssey-bloom-perspective.json for the full colour-coded styling.
// Who has played Odysseus? (a Hollywood A-lister and a man who cast a musical over TikTok)
MATCH p = (:Actor)-[:PLAYS]->({name: "Odysseus"}) RETURN p
// What did EPIC: The Musical cut from Homer?
MATCH (n) WHERE n.notes CONTAINS "Homer only" RETURN n.name, n.description
// The full ten-year commute, Troy to Ithaca
MATCH p = ({name: "Troy"})-[:TRAVELS_TO*]->({name: "Ithaca"}) RETURN p
// Whose story is it, really?
MATCH (n)-[r]-()
WHERE NOT n:Song AND NOT n:Saga AND NOT n:Actor
RETURN n.name AS character, count(r) AS connections
ORDER BY connections DESC LIMIT 10- Five songs are suffixed "(song)" - Odysseus (song), Scylla (song), Charybdis (song), The Underworld (song), Polyphemus (song) - because EPIC names songs after characters and places, and node names must be unique. The blog post tells the full identity-collision story.
- The Trojan War island: Agamemnon, Menelaus, Helen, Clytemnestra, and their actors form
a cluster with no connection to Odysseus's side of the graph. However, in
Book 4, Telemachus visits Menelaus - which you can add yourself with:
MATCH (t {name:"Telemachus"}) MATCH (m {name:"Menelaus"}) MERGE (t)-[:VISITS {detail:"Homer Book 4"}]->(m) - Casting dispute: IMDb lists Charlize Theron as Circe; Wikipedia and Rotten Tomatoes say Calypso (with Samantha Morton as Circe). This dataset follows the two-source majority.
- Film data is cast-only - the film's plot details weren't public when this was compiled (checked 6 Jul 2026).
- Song-to-character
FEATURESlinks were verified by ear against the official albums. Corrections welcome - open an issue or PR.
Homer's Odyssey (Emily Wilson translation) - Theoi.com for lineages - EPIC: The Musical official albums and track lists - Wikipedia, Rotten Tomatoes, IMDb, and BroadwayWorld for cast details. Every row carries its own source column.
- The Odyssey in a Graph Database - the full write-up