The deck's history starts with "Leonhard Euler's paper on "Seven Bridges of Königsberg", published in 1736" (p. 221), drawn as a town map turned into four points and seven lines. Euler's argument, which the slide does not spell out: a walk uses the bridges of every land mass it passes in pairs, in and out, so only its two ends may touch an odd number of bridges. Königsberg's counts were 5, 3, 3, 3 — no walk crosses every bridge once, and no route had to be tried.
Why graphs: property graphs, RDF and Neo4j
After this lesson you will explain why following a relationship in a graph database is a step while a join is a search, use the slides' graph vocabulary, write a Neo4j model in the notation the exam expects, and tell a property graph from an RDF graph of the same facts.
A social network of a million people, each with about fifty friends. Question: who can be reached from one person through at most four friendships? In a test reported in the book Graph Databases by Robinson, Webber and Eifrem (background, not on the slides), MySQL answered in 1,543 seconds — almost 26 minutes — and Neo4j in 1.4 seconds. At five friendships MySQL never finished; Neo4j took 2.1.
Same data, same question. The slide that opens part 2 of the deck gives the verdict without numbers: "Relational Databases (incredibly!) are not good in managing relationships!" (p. 251). By the end of the lesson you will say where a factor of a thousand comes from — and for which kind of question it vanishes.
A graph, in the slides' words
Three kinds of question are graph questions. Neighbourhoods: who are A's friends, and how many? Paths: can a message travel from A to O, and by which shortest route? Patterns: where does a shape occur — two bank accounts sharing one phone number, a sailor who reserved a red boat? Part 1 of the deck (pp. 218–249) supplies the vocabulary; what the text below does not explain, a table lists in the slides' wording.
Informally a graph is "a set of nodes joined by a set of lines or arrows" (p. 224). Formally (p. 225) it is an ordered triple \(G = (V, E, f)\): \(V\) is the set of vertices (nodes), \(E\) the set of edges, and \(f\) a function that "maps each element of E to an unordered pair of vertices in V" — the two endpoints of the edge. Lines are undirected edges. Arrows give a directed graph, in which "An edge is an ordered pair of nodes" (p. 234). Numbers on the edges — distances, costs — make a weighted graph, with a weight function \(w: E \to \R\) (p. 233).
Walking: the path [1, 2, 4, 5] and the cycle 4 → 5 → 4 (p. 229)
Counting: node 2 has in-degree 2 and out-degree 3 (p. 241)
Walk on the left graph of Fig. 1. A path is "a sequence of vertices such that there is an edge from each vertex to its successor", and it is simple "if each vertex is distinct" (p. 229). The slide's example is [1, 2, 4, 5]: 5 is reachable from 1. A path that comes back to its start is a cycle (p. 230): the two arrows between 4 and 5 form one, and so does 1 → 2 → 4 → 1. On the right graph, the degree of a node is the "Number of edges incident on a node" (p. 240); with arrows it splits into in-degree and out-degree, and "Degree = indegree + outdegree" (p. 241): "The in degree of 2 is 2 and the out degree of 2 is 3."
Two definitions are easy to blur. A graph is connected if "any two nodes are connected by a path"; a directed graph is strongly connected if "there is a directed path from any node to any other node" (p. 231) — a path, not a direct edge. And a graph is sparse if \(|E| \approx |V|\), dense if \(|E| \approx |V|^2\) (p. 232). A social network is sparse: fifty friends each, among a million people.
"Strongly connected means every node is directly connected to every other one." So say the course notes, but that is a complete graph. Strongly connected asks only for a directed path: the cycle 1 → 2 → 4 → 1 of Fig. 1 makes its three nodes strongly connected with three arrows, where a complete digraph needs six.
One family deserves a closer look, because its slide has a slip. A complete graph \(K_n\) is one in which "Every pair of vertices are adjacent" (p. 236).
| Term | As the slide puts it | Page |
|---|---|---|
| Famous problems | "The traveling salesman problem"; Francis Guthrie's "four color problem" of 1852, "SOLVED ONLY 120 YEARS LATER!" (in 1976 — background); other examples: wiring, shortest routes, matching, scheduling, visibility | 222–223 |
| Vertex, edge | vertex: "Basic Element", "Drawn as a node or a dot"; edge: "A set of two elements", drawn as a line between its "end vertices, or endpoints" | 226 |
| Example | "V:={1,2,3,4,5,6}", "E:={{1,2},{1,5},{2,3},{2,5},{3,4},{4,5},{4,6}}" — six vertices, seven edges | 227 |
| Simple graph | "graphs without multiple edges or self-loops" | 228 |
| Cyclic, acyclic | "A graph is called cyclic if it contains a cycle; otherwise it is called acyclic" | 230 |
| Bipartite | V "can be partitioned into 2 sets V1 and V2" so that every edge has one end in each | 235 |
| Planar | "Can be drawn on a plane such that no two edges intersect"; "K4 is the largest complete graph that is planar" — although the slide draws K4 with crossing diagonals: one crossing-free drawing is enough (put a corner inside the triangle of the other three) | 237 |
| Tree | "Connected Acyclic Graph"; "Two nodes have exactly one path between them" | 238 |
| Hypergraph | "edges can connect any number of vertices": a pair (X, E), E "a set of subsets of X, called hyperedges" | 239 |
| Subgraph, supergraph | "Vertex and edge sets are subsets of those of G"; a supergraph "contains G as a subgraph" | 242 |
| Spanning subgraph | "Subgraph H has the same vertex set as G", "Possibly not all the edges" | 243 |
| Graph ADT | "a graph is an abstract data type (ADT)": nodes and edges that "establish relationships (connections) between the nodes" | 244 |
| Algorithms | shortest path (single source, all pairs), network flow, matching, topological ordering, strongly connected components; biconnected components and articulation points, bridges, colouring, Euler and Hamiltonian tours, clique, isomorphism, edge and vertex covers, visibility | 248–249 |
Last, the slides store the graph as a data structure, four ways (pp. 245–247): an incidence matrix (edges × vertices), an adjacency matrix (\(|V| \times |V|\), \(a_{ij} = 1\) "if \((i, j) \in E\) and 0 otherwise"), an edge list ("pairs (ordered if directed) of vertices", "Optionally weight and other data") and an adjacency list, every node with the list of its neighbours.
Hold on to that difference. An edge list is a relational table Edge(from, to): finding a node's neighbours means searching it. An adjacency list on disk, every node carrying its own connections, is what the next slides call a graph database.
Following a relationship: a search or a step
After the provocation of the hook (p. 251), part 2 defines its subject (p. 252): a graph database is a "Database that uses graph structures with nodes, edges and properties to store data"; it "Provides index-free adjacency"; its "Edges hold most of the important information".
Index-free adjacency is the technical core. The slide glosses it as "Every node is a pointer to its adjacent element"; read it as: every node stores direct references to its own relationships, and through them to its neighbours. Moving to a neighbour follows a reference — no search, so the cost does not depend on how many other nodes the database holds. In a relational database the same move is a join: the row's key is looked up in an index over the whole table, a search whose cost grows with the table (about \(\log_2\) of its rows), repeated for every row at every hop.
The slide on indexes (p. 272) draws the contrast with two captions. Relational: "Use index scans to look up rows in tables and join them with rows from other tables". Graph: "Use indexes to find the starting points for a query". The widget turns them into numbers.
The model isolates the two effects behind the hook's gap: the join plan carries every repeat of its rows and pays a whole-table search for each; the traversal pays only for the neighbourhood it explores. The measured times have the same shape: close at two hops, far apart from three on.
| Depth (friendships) | MySQL | Neo4j |
|---|---|---|
| 2 | 0.016 | 0.010 |
| 3 | 30.267 | 0.168 |
| 4 | 1,543.505 | 1.359 |
| 5 | did not finish | 2.132 |
The slide's list of advantages (p. 253) follows from the same mechanism. "When there are relationships that you want to analyze, Graph databases become a very nice fit because of the data structure"; they "are very fast for associative data sets — Like social networks"; and they "Map more directly to object oriented applications — Object classification and Parent->Child relationships": objects that reference each other already form a graph, with nothing to flatten into junction tables.
Index-free adjacency: each node stores its own relationships, so a hop is a step and not a search; the index is used once, to find where to start.
"Foreign Keys? No thanks": from tables to a property graph
The deck makes the argument on one example, the Sailors database (p. 254): Sailor(sid, sname, rating, age), Boat(bid, bname, color) and Reserve(sid, bid, day), with the keys underlined — all three columns for Reserve. Reserve is a junction table, the relational way to store a many-to-many relationship: two foreign keys plus the relationship's own attribute, day.
Before: three tables and two foreign keys (p. 254)
After: the reservations are relationships with a day (pp. 256–257)
day, and the copied keys sid and bid are gone. Sailor 31 and boat 102 simply have no relationship.Page 255 redraws the tables as a generic graph, every table, row, attribute and value an oval: possible, and unreadable. Page 256 gives the "Actual Graph Model" in one line, (:Sailor) –[:reserves]-> (:Boat), and page 257 the reason, "Foreign Keys? No thanks": the reservation links directly to its sailor and its boat, so its copies of sid = 22 and bid = 101 are crossed out and only day stays. In the property graph the reservation is a relationship, and the day its property.
That is the property graph, Neo4j's model. The slide gives it in three bullets — "Nodes – with labels (type) and attributes", "Edges", "Indexes" (p. 266) — and Neo4j's documentation (background) completes it:
- a node has zero or more labels, its types (
:Sailor; p. 269 creates one node with two,:Actor:Director), and properties, key-value pairs; - a relationship — the slides' edge — has exactly one type (
:RESERVES), a direction from a start node to an end node, and properties of its own; - property values are typed: String, Integer, Float, Boolean, Date and the other temporal types, and lists of these.
At the exam the model is written in the notation of p. 256. The paper of 30 Jan 2026 asks for "a written textual representation (no graphical sketches) of the graph model, using the typical Neo4J notation for nodes ( ), edges -[ ]->, and attributes { }. Include data types for attributes." For the Sailors:
// the Sailors of p. 254 as a graph model
(:Sailor {sid: Integer, sname: String,
rating: Integer, age: Float})
(:Boat {bid: Integer, bname: String, color: String})
(:Sailor)-[:RESERVES {day: Date}]->(:Boat)
Labels in CamelCase, types in capitals, no keys copied onto the edge: "N:N relationship do not need any special treatment" (p. 1385). The full recipe — ISA hierarchies, the past papers — is lesson 12.
"In CREATE (Neo:Crew { name:'Neo' }) (p. 268), Neo is the label." The course notes say so, but Neo is a variable — the name the statement uses for the node while it runs. Crew is the label, name a property. Nothing called Neo is stored except the value of that property.
A query on such a graph is a shape. "Query: Graph matching approach" (p. 258) draws a small shape found three times inside a large blob of "Facts": you describe a pattern — a sailor, a RESERVES arrow, a red boat — and the database returns every place where it occurs; in Fig. 3, twice. And the graph needs no schema migration: a book that gains a second author gets one more edge ("Easy to Extend", p. 259), and a stored value can be replaced by a node computed from other measurements ("Easy to Change", p. 260).
The same facts as RDF triples
The exam guideline lists, under "Features of Graph DB", two models: "Property graphs (neo4j)" and "Direct labelled graphs (RDF)" — "direct" meaning directed. The slides never name RDF, but they draw it: pages 255 and 257, with every attribute an oval at the end of an arrow, are in the RDF style. What follows on RDF itself is background from the W3C's RDF 1.1 Primer.
In RDF (Resource Description Framework) everything is a triple: "A statement always has the following structure: <subject> <predicate> <object>". Subjects and predicates are IRIs — web identifiers such as http://example.org/sailing#s22, abbreviated :s22 — and an object is an IRI or a literal value. An RDF graph is a set of triples; drawn as arrows from subject to object, labelled with their predicates, they form a directed labelled graph. An attribute is just an arrow that ends in a literal, :s22 :sname "dustin", and a label becomes the triple :s22 rdf:type :Sailor.
:res1 — the node ID4 that the slide draws on p. 257 with its sailor, its boat and its day.The difference shows on the relationship. In the property graph the reservation is one relationship with a property. A triple has three places and no fourth, so to record the day RDF turns the reservation into a resource — reification — with a triple to the sailor, one to the boat and one for the day.
RDF is queried with SPARQL, the W3C's language, whose patterns are triples with variables. One question in three models — the names of the sailors who reserved a red boat. SQL needs two joins:
-- SQL over the tables of p. 254: two joins
SELECT DISTINCT S.sname
FROM Sailor S
JOIN Reserve R ON R.sid = S.sid
JOIN Boat B ON B.bid = R.bid
WHERE B.color = 'red';
In Cypher, Neo4j's query language, the two joins become one arrow — the lesson's only query, a taste of lesson 11:
// returns dustin and rusty (Fig. 3)
MATCH (s:Sailor)-[:RESERVES]->(b:Boat {color: 'red'})
RETURN DISTINCT s.sname
In SPARQL the same pattern is written as triples, one per arrow (here over the triples without the day):
# one triple pattern per arrow
PREFIX : <http://example.org/sailing#>
SELECT DISTINCT ?name
WHERE {
?s a :Sailor ;
:sname ?name ;
:reserves ?b .
?b :color "red" .
}
Nodes with labels and properties; relationships with one type, a direction and properties. Two relationships between the same nodes are two things. Queried with Cypher; built as an application database for fast traversals.
A set of subject–predicate–object triples on IRIs. Attributes are arrows to literals; a relationship has no properties and no identity unless reified. Queried with SPARQL; built to publish and link data through shared identifiers.
Neo4j, as the slides present it
Part 3 introduces the product (p. 262): "Developed by Neo Technologies • Most Popular Graph Database • Implemented in Java • Open Source". Its "Salient features" (p. 263): "Neo4j is schema free – Data does not have to adhere to any convention"; "ACID – atomic, consistent, isolated and durable for logical units of work"; easy to use, well documented, and "Support for wide variety of languages — Java, Python, Perl, Scala, Cypher, etc" (Cypher is the query language, the others client languages).
Read the bottom layer with index-free adjacency in mind. Nodes and relationships live in separate record files; in the book Graph Databases (ch. 6, background) a node record points to its first relationship, and each relationship record to the previous and next relationships of both its nodes — the references a traversal follows. The transaction log lets committed work survive a crash: the D of ACID.
"Purpose" (p. 265) is the most quotable slide of part 3: "Meant to be an operational DB, not specifically for analytics • ACID • Efficient on nodes • Not so efficient in whole-graph analysis". Neo4j serves an application with many small transactions that start at a node — who are my friends, add this reservation — cheap thanks to index-free adjacency; ranking every page of the web gains nothing from local pointers. ACID matters in a graph because creating a relationship touches two nodes: only a transaction keeps an edge from pointing at a node that is gone. The course notes add a "traditional CA architecture" (lesson 5); the slides do not.
Cypher, the slide says (p. 267), is a "Declarative language", "Easy to formulate queries based on relationships", whose features "stem from improving on pain points with SQL such as join tables": you state the pattern, Neo4j chooses the traversal. Then data comes in. CREATE makes nodes, with several labels if needed — Create (n:Actor:Director {name:'Clint Eastwood'}) (p. 269); LOAD CSV WITH HEADERS ... AS row runs the statement once per line of a file, reading columns as row.Column. Run a CREATE import twice and every node exists twice — hence MERGE, "ID-based" (p. 270):
// p. 270: one Player node per id
LOAD CSV WITH HEADERS FROM "file:///transfers.csv" AS row
MERGE (player:Player {id: row.playerUri})
ON CREATE SET player.name = row.playerName,
player.position = row.playerPosition
MERGE is match-or-create on the whole pattern, label and properties: a :Player with that id is used if it exists, created otherwise, and ON CREATE SET fills the other properties only when it is created. A player mentioned in many rows still becomes one node. Page 271 then imports the transfers:
// p. 271: a transfer becomes a node
LOAD CSV WITH HEADERS FROM "file:///transfers.csv" AS row
MATCH (player:Player {id: row.playerUri})
MATCH (source:Club {id: row.sellerClubUri})
MATCH (destination:Club {id: row.buyerClubUri})
MERGE (t:Transfer {id: row.transferUri})
ON CREATE SET t.season = row.season, t.rank = row.transferRank,
t.fee = row.transferFee
MERGE (t)-[:OF_PLAYER { age: row.playerAge }]->(player)
MERGE (t)-[:FROM_CLUB]->(source)
MERGE (t)-[:TO_CLUB]->(destination)
A transfer links three things — a player, a selling club, a buying club — and a relationship joins exactly two nodes, so the transfer becomes a node with three typed relationships: the hyperedge of p. 239, whose "edges can connect any number of vertices", turned into a node. The player's age at the time is a property of OF_PLAYER, the "important information" an edge holds.
"MERGE creates new nodes only if it doesn't exist another node with the same label" — so the course notes. Taken literally, the import above would create one Player in all. MERGE compares the whole pattern: one Player per id.
Two schema statements follow. An index is "For performance purpose" and "Only for access to initial node of the query" (p. 272): it finds the anchor, say customer 42; later hops follow relationships. A uniqueness constraint (p. 273) forbids two :Customer nodes with the same customerID — the graph's primary key, which keeps a MERGE by id honest. Schema free means nothing has to be declared, not that nothing can be. The slides print Neo4j 3 syntax, which Neo4j 5 rejects; today you write FOR … ON and FOR … REQUIRE, with an optional name:
CREATE INDEX ON
:Customer(customerID);
CREATE CONSTRAINT ON (c:Customer)
ASSERT c.customerID IS UNIQUE;
CREATE INDEX customer_id
FOR (c:Customer) ON (c.customerID)
CREATE CONSTRAINT customer_key
FOR (c:Customer)
REQUIRE c.customerID IS UNIQUE
"A query starts with START." The skeleton of p. 274 lists "START", "MATCH Pattern Matching", "WHERE Expressions, Predicates", "RETURN Output". START picked the starting nodes from an index in Neo4j 1.x; since 2.0 a label and a property inside MATCH do it, and current Neo4j rejects START. Begin every exam query with MATCH, as the exercise sessions do.
The next pages show the query language itself. You learn to write it in lesson 11 and lesson 12; here is what the slides print, for a closed question that quotes them.
| Slide | What it prints, and how to read it | Page |
|---|---|---|
| The Matrix query | MATCH (n:Crew)-[r:KNOWS*]-m WHERE n.name='Neo' RETURN n AS Neo,r,m, with a result of four rows.Read: every path of one or more KNOWS relationships, in either direction, starting at Neo — one row per path, ending at Morpheus, Trinity, Cypher and Agent Smith. Today the end node needs parentheses, -(m), and the * a bound (p. 282). | 275 |
| General Query Format | MATCH (user)-[:FRIEND]-(friend) WITH user, count(friend) AS friends ORDER BY friends DESC SKIP 1 LIMIT 3 RETURN user; "WITH separates query parts explicitly, to declare the variables for the next part"; "SKIP skips results at the top and LIMIT limits the number of results".Read: count the friends of each user (the non-aggregated user is the grouping key), sort, skip the first, keep three — the users ranked second to fourth. The template of the exam queries. | 276 |
| Patterns | (n:Person:Swedish) "Node with both Person and Swedish labels"; (n)--(m) "Relationship in any direction between n and m"; (m)<-[:KNOWS]-(n) "Relationship of type KNOWS from n to m"; (n)-[:KNOWS|:LOVES]->(m) "of type KNOWS or of type LOVES"; (n)-[*1..5]->(m) "Variable length path from 1 to 5 rels."Read: the arrowhead gives the direction, not the order of the text; $value in a property map is a parameter. Neo4j 5 writes [:KNOWS|LOVES], with one colon. | 277–278 |
| Paths | shortestPath((n1:Person)-[*..6]-(n2:Person)) "Find a single shortest path"; allShortestPaths((n1:Person)-[*..6]->(n2:Person)) "Find all shortest paths"; size((n)-->()-->()) "Count the paths matching the pattern".Read: one, or every, shortest connection of at most 6 relationships between two people. Neo4j 5 removed size() on a pattern and writes COUNT { (n)-->()-->() }. | 280 |
| Core operators and impact | Cypher's clauses drawn as a graph: MATCH DESCRIBES a Pattern, which is FOUND_IN the Graph and BUILDS_UP the Result; WHERE FILTERS it, Aggregation RESTRUCTURES it, SKIP/LIMIT PAGINATES it; CREATE and DELETE change the Graph. Read: the picture also has START and RELATE, which no longer exist — MERGE took over RELATE's job. | 281 |
Four "Hints" (p. 282) close the Cypher part, each with its reason: "Use parameters instead of literals" — with $name in place of 'dustin' the query text stays the same and Cypher re-uses its plan; "Always set an upper limit for your variable length patterns" — every hop multiplies the paths, and "It's easy to have a query touch all nodes in a graph by mistake"; "Return only the data you need"; "Use PROFILE / EXPLAIN". "Stored Procedures" (p. 279) are Java functions: "Simply move your JAR to a folder!", then call them from Cypher — which is also how libraries of whole-graph algorithms are plugged in (background).
When a graph wins — the puzzle resolved
The uses follow from "Efficient on nodes": questions that start somewhere and walk. Social networks, the slide's example (p. 253): in 2016 Facebook found its 1.59 billion users on average 3.57 intermediaries apart — four or five friendships, the depths where the joins of the hook crawled or never finished. Recommendation: people you may know are friends of friends who are not yet friends. Fraud: a ring of fake identities sharing one phone number and one address is a few hops in a graph and a chain of self-joins in SQL. Routing: "Shortest route between two cities" (p. 223) on a weighted graph — on p. 233 the direct edge from 2 to 5 costs 5, the detour through 1 costs 2 + 1 = 3. Investigation: journalists explored the Panama Papers as a Neo4j graph of about 950,000 nodes and 1.2 million relationships.
the value is in the links: many-to-many relationships, paths of unknown length, rings and shared neighbours; questions start from a node and stay local; the structure keeps changing.
records have a fixed shape, joins a small fixed depth, and questions are set-oriented — totals and reports over all rows — under the strict schema of lessons 8 and 9. Whole-graph analysis suits neither: it belongs to batch frameworks.
Now the puzzle. At four friendships the relational query is a chain of four self-joins: for every row produced so far, an index over some fifty million friendship rows is searched, and those rows include every repeat, because friends share friends. Neo4j searches an index once, to find the starting person, then follows the relationships stored with each person it reaches — work proportional to the neighbourhood, not to the database. At two friendships there is little to gain (0.016 s against 0.010 s); each further hop multiplies the relational work. The gap closes when the question stops being local: for every node at once, pointers offer no shortcut — "Not so efficient in whole-graph analysis" (p. 265). The slide's "(incredibly!)" holds for relationships followed many hops deep; joined one level at a time, they are the relational database's daily work.
Exam-style questions
Theory questions in the form of the written exam — open answers of a few sentences, and closed ones where a wrong tick may cost points — then two exercises in the form of the first part of every Neo4j exercise. The split of the 6 theory points is not published, so the theory questions carry no points.
What is index-free adjacency? Explain why it makes traversing relationships in a graph database cheaper than joins in a relational database, and say what indexes are used for in Neo4j.
Show model answer
A graph database "provides index-free adjacency": every node stores direct references to its adjacent relationships and, through them, to its neighbouring nodes. Moving from a node to its neighbours is therefore a pointer dereference, whose cost depends on that node's relationships and not on the size of the whole graph. In a relational database a relationship is a foreign key, and following it is a join: for each row an index built over the whole table is searched, at a cost that grows with the table (about log n), and this is repeated at every hop while the intermediate results grow, since friends share friends. For deep or variable-depth traversals, such as friends of friends of friends, the graph database does far less work; at one hop there is no difference. In Neo4j indexes are used only to find the starting nodes of a query; from there the traversal follows the stored relationships.
Three things earn the answer: the definition in the slide's words (index-free adjacency, p. 252), the reason (a step against a search whose cost grows with the table) and the role of indexes (starting points, p. 272). The measured times of the hook are a bonus; if you quote them, say they come from the book Graph Databases.
Compare property graphs (Neo4j) and directed labelled graphs (RDF). Where do the attributes live in each model, and how would each store the day of a reservation that links a sailor to a boat?
Show model answer
A property graph is made of nodes, relationships and properties. Nodes carry zero or more labels and key-value properties; relationships are directed, have exactly one type and can carry properties too. The reservation is one relationship with a property: (:Sailor {sid: 22})-[:RESERVES {day: date('1996-10-10')}]->(:Boat {bid: 101}). An RDF graph is a set of subject–predicate–object triples whose subjects and predicates are IRIs: every attribute is itself an edge from a resource to a literal (:s22 :sname "dustin"), and a label is an rdf:type triple. A relationship is just a triple and cannot carry an attribute, so to store the day the reservation must become a resource of its own (reification): :res1 :sailor :s22, :res1 :boat :b101, :res1 :day "1996-10-10". Property graphs are queried with Cypher and built as application databases with fast traversals; RDF is queried with SPARQL and built to publish and link data through shared identifiers.
This is the guideline's theory item word for word: "Property graphs (neo4j)", "Direct labelled graphs (RDF)". The slides draw the RDF style (pp. 255–257) without naming it, so a strong answer rests on the contrast — where attributes live, what happens to a relationship that has an attribute — rather than on RDF syntax.
According to the lecture, which of the following describe Neo4j? Select all that apply.
Show model answer
Schema free, ACID, and meant to be an operational database. Neo4j is "Not so efficient in whole-graph analysis", uses indexes only to find the starting nodes of a query, and allows several labels per node.
Three right options out of six. When wrong ticks may cost points, the safe ticks are the phrases printed on pp. 263 and 265; the wrong options are the three classic confusions — analytics, indexes, labels.
How many edges does the complete undirected graph \(K_7\) have?
Show model answer
Every unordered pair of the 7 vertices is one edge.
The slide prints "Has n(n-1) edges", which gives 42: the arrows of a complete directed graph. Its own drawing of \(K_4\) has 6 edges. If a closed question offers both 21 and 42, choose by the graph — 21 undirected, 42 with both directions.
True or false: the query MATCH (user)-[:FRIEND]-(friend) WITH user, count(friend) AS friends ORDER BY friends DESC SKIP 1 LIMIT 3 RETURN user returns the three users with the most friends.
Show model answer
False. WITH counts the friends of each user, ORDER BY sorts the users by that count in descending order, SKIP 1 drops the first one and LIMIT 3 keeps the next three: the users ranked second to fourth.
The query is the "General Query Format" of p. 276, word for word. A true/false item tests one clause at a time; here the trap is SKIP. Users with the same count have no defined order unless you add a second sort key.
Consider the Sailors example of the lecture (p. 254) as an ER model. The following attributes describe the entities; the primary keys are underlined. Sailor - sid (integer), sname, rating (integer), age (real). Boat - bid (integer), bname, color. The relationship Reserve links Sailor (0,N) and Boat (0,N) and has the attribute day (a date).
Suppose you want to store the respective data instances in a graph database. Provide a written textual representation of the graph model, using the typical Neo4J notation for nodes ( ), edges -[ ]->, and attributes { }. Include data types for attributes. Then write one example instance: sailor 22 (dustin, rating 7, age 45.0) reserved boat 101 (Interlake, red) on 10/10/96.
Show model answer
(:Sailor {sid: Integer, sname: String,
rating: Integer, age: Float})
(:Boat {bid: Integer, bname: String, color: String})
(:Sailor)-[:RESERVES {day: Date}]->(:Boat)
(:Sailor {sid: 22, sname: "dustin", rating: 7, age: 45.0})
-[:RESERVES {day: date("1996-10-10")}]->
(:Boat {bid: 101, bname: "Interlake", color: "red"})
Reserve is not a node: it is the relationship, and its attribute day is a property of the edge. There is no sid or bid on the edge either: the edge itself links the sailor and the boat, where the relational schema of the lecture needed them as foreign keys.
The wording is that of the exam of 30 Jan 2026 (2 PT there), the first part of every Neo4j exercise; in 2024–2025 it was a 1-point "sketch". No grading scheme is published, but these go against the recipe of the exercise sessions (p. 1385) or against the question: a Reserve node, sid and bid repeated on the edge, a relationship without a type or without a direction, missing data types. Past papers write dates as dd/mm/yyyy: store them as Date and say which format you assume.
Consider an ER model of football transfers, the data imported on p. 271. The following attributes describe the entities; the primary keys are underlined. Player - Player_ID, Name, Position. Club - Club_ID, Name. Transfer - Transfer_ID, Season, Rank, Fee. Relationships: Of_Player links Transfer (1,1) and Player (0,N) and has the attribute Age, the player's age at the time of the transfer; From_Club and To_Club each link Transfer (1,1) and Club (0,N): the club that sells and the club that buys.
Provide a written textual representation of the graph model, using the typical Neo4J notation for nodes ( ), edges -[ ]->, and attributes { }, with data types. Explain why Transfer is a node and not a relationship.
Show model answer
(:Player {player_id: String, name: String, position: String})
(:Club {club_id: String, name: String})
(:Transfer {transfer_id: String, season: String,
rank: Integer, fee: Float})
(:Transfer)-[:OF_PLAYER {age: Integer}]->(:Player)
(:Transfer)-[:FROM_CLUB]->(:Club)
(:Transfer)-[:TO_CLUB]->(:Club)
A transfer links three nodes — a player, a selling club and a buying club — and has attributes of its own, while a Neo4j relationship joins exactly two nodes; so the transfer becomes a node with three typed relationships. The player's age belongs to the link between the transfer and the player and is a property of OF_PLAYER. The two relationships to Club are told apart by their types, FROM_CLUB and TO_CLUB.
This is the model behind the import of p. 271. A design such as (:Club)-[:TRANSFERS {player: …, fee: …}]->(:Club) loses the player as a node: you could no longer walk from a player to his transfers. The same move — an entity with several partners stays a node — returns in past papers, for example Ticket in the exam of 11 Feb 2025; ISA hierarchies and the rest of the recipe are lesson 12.
Check yourself
A's circle stays exactly as in the first widget, but the Friendship table around it grows from 34 rows to 50 million. At depth 3, which numbers change?
Which statements about the property graph model of Neo4j are true? Select all that apply.
Labels on nodes, one type on each relationship, properties on both.
In the RDF view of the second widget, dustin books Interlake a second time and the reservation has no day. How many triples does the second booking add?
In a property graph two relationships between the same nodes are two things; in RDF a statement has no identity unless you make it a node.
The slide says \(K_n\) "Has n(n-1) edges". For \(n = 4\) that is 12. Which of these quantities are 12? Select all that apply.
\(n(n-1)\) counts each edge twice; halve it for the undirected \(K_n\).
Which of these directed graphs on the nodes 1, 2, 3 is strongly connected?
Strongly connected needs a directed path between every pair, not a direct edge — a direct edge everywhere is a complete graph, the course notes' slip.
A file of transfers mentions player p7 in three rows. The import of p. 270 runs MERGE (player:Player {id: row.playerUri}) once per row. How many Player nodes with id p7 exist afterwards?
A query starts from customer 42 and follows two relationships from there. There is an index on :Customer(customerID). Where does Neo4j use it?
Key take-aways
- A graph is \(G = (V, E, f)\): vertices, edges, and the function that gives each edge its two endpoints. Arrows make it directed, numbers on the edges make it weighted; path, cycle, (strongly) connected and degree (in + out) describe the three graph questions — neighbourhoods, paths and patterns. \(K_n\) has \(n(n-1)/2\) edges; the slide prints \(n(n-1)\).
- A graph database "uses graph structures with nodes, edges and properties to store data" and "provides index-free adjacency": each node stores its relationships, so a hop is a step whose cost does not depend on the size of the database, while a join is an index search for every row at every hop. Neo4j uses indexes only to find the starting nodes.
- In the property graph, nodes have labels and properties, relationships have exactly one type, a direction and properties. A junction table becomes a relationship that keeps its attributes ("Foreign Keys? No thanks"); a link among three things becomes a node.
- In RDF, a set of subject–predicate–object triples on IRIs, attributes are arrows to literals, a label is an
rdf:typetriple, and a relationship gets properties or an identity only by being reified as a resource; SPARQL queries it. - Neo4j is schema free, ACID, "Meant to be an operational DB", "Efficient on nodes", "Not so efficient in whole-graph analysis"; records for nodes, relationships and properties sit next to a transaction log. MERGE is match-or-create on the whole pattern; a uniqueness constraint is the graph's key; the slides print Neo4j 3 syntax.
- Graphs win on local questions that walk many hops — social networks, recommendation, fraud rings, routing; relational databases on set-oriented work over records of a fixed shape. The hook's factor of a thousand is a search per row against a step per relationship, multiplied over four hops.
What to watch and read
-
Introduction to Graph Theory: A Computer Science Perspective
Reducible
The vocabulary of section 1 animated, ending with the same graph as a drawing, an adjacency matrix and an adjacency list — and why software that walks neighbours wants the list.
-
Graph database concepts
Neo4j documentation
The property graph in Neo4j's own words — labels, one type and one direction per relationship, properties on both — the complete version of the three-word data-model slide.
-
RDF vs. property graphs: choosing the right approach for implementing a knowledge graph
Jim Webber, Neo4j, 2024
Why a property on a relationship costs extra triples in RDF, and how the two models were designed for different jobs. Written by the property-graph side, so read it as one argument.
-
Graph Databases, 2nd edition
Ian Robinson, Jim Webber, Emil Eifrem
Free after registration. Chapter 2 holds the friends-of-friends table of the hook; chapter 6 draws the record files of Fig. 5 and the pointers between them.
-
The Graph Traversal Pattern
Marko A. Rodriguez, Peter Neubauer, 2010
The paper that named index-free adjacency: local traversals against the index-intensive joins of relational databases.