In this webinar we'll explore a data set using Neo4j and Cypher and compare the approach we might take with a relational database and SQL. We'll cover the following topics: Modeling the data set Importing the data Querying the data Evolving the model and queries as the data changes.
18. CREATE TABLE players (
"id" character varying(100)
NOT NULL PRIMARY KEY,
"name" character varying(150) NOT NULL,
"position" character varying(20)
);
19. INSERT INTO players
VALUES('/aldair/profil/spieler/4151', 'Aldair', 'Centre Back');
INSERT INTO players
VALUES('/thomas-hassler/profil/spieler/553', 'Thomas Häßler',
'Attacking Midfield');
INSERT INTO players VALUES('/roberto-baggio/profil/spieler/4153',
'Roberto Baggio', 'Secondary Striker');
20. CREATE TABLE clubs (
"id" character varying(100)
NOT NULL PRIMARY KEY,
"name" character varying(50) NOT NULL,
"country" character varying(50)
);
21. INSERT INTO clubs VALUES('/hertha-bsc/startseite/verein/44',
'Hertha BSC', 'Germany');
INSERT INTO clubs VALUES('/cfr-cluj/startseite/verein/7769', 'CFR
Cluj', 'Romania');
INSERT INTO clubs VALUES('/real-sociedad/startseite/verein/681',
'Real Sociedad', 'Spain');
22. CREATE TABLE transfers (
"id" character varying(100) NOT NULL PRIMARY KEY,
"fee" character varying(50) NOT NULL,
"numericFee" integer NOT NULL,
"player_age" smallint NOT NULL,
"season" character varying(5) NOT NULL,
"player_id" character varying(100) NOT NULL REFERENCES players (id),
"from_club_id" character varying(100) NOT NULL REFERENCES clubs (id),
"to_club_id" character varying(100) NOT NULL REFERENCES clubs (id)
);
36. LOAD CSV WITH HEADERS FROM "file:///transfers.csv" AS row
CREATE (player:Player {
id: row.playerUri,
name: row.playerName,
position: row.playerPosition
})
Node 25 already exists with label Player and property
"id"=[/peter-lux/profil/spieler/84682]
37. 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
39. LOAD CSV WITH HEADERS FROM "file:///transfers.csv" AS row
MERGE (club:Club {id: row.sellerClubUri})
ON CREATE SET club.name = row.sellerClubName,
club.country = row.sellerClubCountry;
LOAD CSV WITH HEADERS FROM "file:///transfers.csv" AS row
MERGE (club:Club {id: row.buyerClubUri})
ON CREATE SET club.name = row.buyerClubName,
club.country = row.buyerClubCountry;
53. SELECT *
FROM players
WHERE players.name = 'Cristiano Ronaldo'
MATCH (player:Player { name: "Cristiano Ronaldo" })
RETURN player
54. SELECT *
FROM players
WHERE players.name = 'Cristiano Ronaldo'
MATCH (player:Player { name: "Cristiano Ronaldo" })
RETURN player
55. SELECT *
FROM players
WHERE players.name = 'Cristiano Ronaldo'
MATCH (player:Player { name: "Cristiano Ronaldo" })
RETURN player
56.
57.
58. SELECT players.name, t."numericFee", t.season
FROM transfers AS t
JOIN clubs AS clubFrom ON t.from_club_id = clubFrom.id
JOIN clubs AS clubTo ON t.to_club_id = clubTo.id
JOIN players ON t.player_id = players.id
WHERE clubFrom.name = 'Tottenham Hotspur' AND clubTo.name = 'Manchester United'
59. SELECT players.name, t."numericFee", t.season
FROM transfers AS t
JOIN clubs AS clubFrom ON t.from_club_id = clubFrom.id
JOIN clubs AS clubTo ON t.to_club_id = clubTo.id
JOIN players ON t.player_id = players.id
WHERE clubFrom.name = 'Tottenham Hotspur' AND clubTo.name = 'Manchester United'
MATCH (from:Club)<-[:FROM_CLUB]-(transfer:Transfer)-[:TO_CLUB]->(to:Club),
(transfer)-[:OF_PLAYER]->(player)
WHERE from.name = "Tottenham Hotspur" AND to.name = "Manchester United"
RETURN player.name, transfer.numericFee, transfer.season
60. SELECT players.name, t."numericFee", t.season
FROM transfers AS t
JOIN clubs AS clubFrom ON t.from_club_id = clubFrom.id
JOIN clubs AS clubTo ON t.to_club_id = clubTo.id
JOIN players ON t.player_id = players.id
WHERE clubFrom.name = 'Tottenham Hotspur' AND clubTo.name = 'Manchester United'
MATCH (from:Club)<-[:FROM_CLUB]-(transfer:Transfer)-[:TO_CLUB]->(to:Club),
(transfer)-[:OF_PLAYER]->(player)
WHERE from.name = "Tottenham Hotspur" AND to.name = "Manchester United"
RETURN player.name, transfer.numericFee, transfer.season
69. UPDATE players
SET nationality = 'Brazil'
WHERE players.id = '/aldair/profil/spieler/4151';
UPDATE players
SET nationality = 'Germany'
WHERE players.id ='/ulf-kirsten/profil/spieler/74';
UPDATE players
SET nationality = 'England'
WHERE players.id ='/john-lukic/profil/spieler/28241';
70.
71.
72. LOAD CSV WITH HEADERS FROM "file:///transfers.csv" AS row
MATCH (player:Player {id: row.playerUri})
SET player.nationality = row.playerNationality
73.
74. SELECT players.name, clubFrom.name, clubTo.name, t."numericFee", t.season
FROM transfers AS t
JOIN clubs AS clubFrom ON t.from_club_id = clubFrom.id
JOIN clubs AS clubTo ON t.to_club_id = clubTo.id
JOIN players ON t.player_id = players.id
WHERE clubFrom.country = 'England' AND clubTo.country = 'England'
AND players.nationality = 'England'
ORDER BY t."numericFee" DESC
LIMIT 10
75. SELECT players.name, clubFrom.name, clubTo.name, t."numericFee", t.season
FROM transfers AS t
JOIN clubs AS clubFrom ON t.from_club_id = clubFrom.id
JOIN clubs AS clubTo ON t.to_club_id = clubTo.id
JOIN players ON t.player_id = players.id
WHERE clubFrom.country = 'England' AND clubTo.country = 'England'
AND players.nationality = 'England'
ORDER BY t."numericFee" DESC
LIMIT 10
MATCH (to:Club)<-[:TO_CLUB]-(t:Transfer)-[:FROM_CLUB]-(from:Club), (t)-[:OF_PLAYER]->(player:Player)
WHERE to.country = "England" AND from.country = "England" AND player.nationality = "England"
RETURN player.name, from.name, to.name, t.numericFee, t.season
ORDER BY t.numericFee DESC
LIMIT 10
76. SELECT players.name, clubFrom.name, clubTo.name, t."numericFee", t.season
FROM transfers AS t
JOIN clubs AS clubFrom ON t.from_club_id = clubFrom.id
JOIN clubs AS clubTo ON t.to_club_id = clubTo.id
JOIN players ON t.player_id = players.id
WHERE clubFrom.country = 'England' AND clubTo.country = 'England'
AND players.nationality = 'England'
ORDER BY t."numericFee" DESC
LIMIT 10
MATCH (to:Club)<-[:TO_CLUB]-(t:Transfer)-[:FROM_CLUB]-(from:Club), (t)-[:OF_PLAYER]->(player:Player)
WHERE to.country = "England" AND from.country = "England" AND player.nationality = "England"
RETURN player.name, from.name, to.name, t.numericFee, t.season
ORDER BY t.numericFee DESC
LIMIT 10
77.
78. |----------------------+----------------|
| country | confederation |
|----------------------+----------------|
| Afghanistan | afc |
| Albania | uefa |
| Algeria | caf |
| American Samoa | ofc |
| Andorra | uefa |
| Angola | caf |
| Anguilla | concacaf |
| Antigua and Barbuda | concacaf |
| Argentina | conmebol |
|----------------------+----------------|
|-----------+-----------+-------------------------------------------------|
| urlName | shortName | region |
|-----------+-----------+-------------------------------------------------|
| afc | AFC | Asia |
| uefa | UEFA | Europe |
| ofc | OFC | Oceania |
| conmebol | CONMEBOL | South America |
| concacaf | CONCACAF | North American, Central American and Caribbean |
| caf | CAF | Africa |
|-----------+-----------+-------------------------------------------------|
81. CREATE TABLE confederations (
"id" character varying(10)
NOT NULL PRIMARY KEY,
"shortName" character varying(50) NOT NULL,
"name" character varying(100) NOT NULL,
"region" character varying(100) NOT NULL
);
82. INSERT INTO confederations VALUES('afc', 'AFC', 'Asian Football
Confederation', 'Asia');
INSERT INTO confederations VALUES('uefa', 'UEFA', 'Union of
European Football Associations', 'Europe');
INSERT INTO confederations VALUES('ofc', 'OFC', 'Oceania Football
Confederation', 'Oceania');
83. CREATE TABLE countries (
"code" character varying(3)
NOT NULL PRIMARY KEY,
"name" character varying(50)
NOT NULL,
"federation" character varying(10) NOT NULL
REFERENCES confederations (id)
);
84. INSERT INTO countries VALUES('MNE', 'Montenegro', 'uefa');
INSERT INTO countries VALUES('LTU', 'Lithuania', 'uefa');
INSERT INTO countries VALUES('CAM', 'Cambodia', 'afc');
INSERT INTO countries VALUES('SUI', 'Switzerland', 'uefa');
INSERT INTO countries VALUES('ETH', 'Ethiopia', 'caf');
INSERT INTO countries VALUES('ARU', 'Aruba', 'concacaf');
INSERT INTO countries VALUES('SWZ', 'Swaziland', 'caf');
INSERT INTO countries VALUES('PLE', 'Palestine', 'afc');
85. ALTER TABLE clubs
ADD COLUMN country_id character varying(3)
REFERENCES countries(code);
86. UPDATE clubs AS cl
SET country_id = c.code
FROM clubs
INNER JOIN countries AS c
ON c.name = clubs.country
WHERE cl.id = clubs.id;
87. # select * from clubs limit 5;
id | name | country | country_id
----------------------------------------+-----------------------------+---------------+------------
/san-jose-clash/startseite/verein/4942 | San Jose Clash | United States | USA
/chicago/startseite/verein/432 | Chicago Fire | United States | USA
/gz-evergrande/startseite/verein/10948 | Guangzhou Evergrande Taobao | China | CHN
/as-vita-club/startseite/verein/2225 | AS Vita Club Kinshasa | Congo DR | CGO
/vicenza/startseite/verein/2655 | Vicenza Calcio | Italy | ITA
(6 rows)
90. UPDATE players AS p
SET country_id = c.code
FROM players
INNER JOIN countries AS c
ON c.name = players.nationality
WHERE p.id = players.id;
91. # select * from players limit 5;
id | name | position | nationality | country_id
-----------------------------------------+-------------------+--------------------+-------------+------------
/dalian-atkinson/profil/spieler/200738 | Dalian Atkinson | Attacking Midfield | England | ENG
/steve-redmond/profil/spieler/177056 | Steve Redmond | Centre Back | England | ENG
/bert-konterman/profil/spieler/6252 | Bert Konterman | Centre Back | Netherlands | NED
/lee-philpott/profil/spieler/228030 | Lee Philpott | Midfield | England | ENG
/tomasz-frankowski/profil/spieler/14911 | Tomasz Frankowski | Centre Forward | Poland | POL
(5 rows)
95. LOAD CSV WITH HEADERS FROM "file:///confederations.csv" AS row
MERGE (c:Confederation {id: row.urlName})
ON CREATE SET c.shortName = row.shortName,
c.region = row.region,
c.name = row.name
96. LOAD CSV WITH HEADERS FROM "file:///countries.csv" AS row
MATCH (conf:Confederation {id: row.confederation })
MERGE (country:Country {id: row.countryCode})
ON CREATE SET country.name = row.country
MERGE (country)-[:PART_OF]->(conf)
100. SELECT players.name, clubFrom.name, clubTo.name, t."numericFee", t.season
FROM transfers AS t
JOIN clubs AS clubFrom ON t.from_club_id = clubFrom.id
JOIN clubs AS clubTo ON t.to_club_id = clubTo.id
JOIN players ON t.player_id = players.id
WHERE clubFrom.country = 'England' AND clubTo.country = 'England'
AND players.nationality = 'England'
ORDER BY t."numericFee" DESC
LIMIT 10
MATCH (to:Club)<-[:TO_CLUB]-(t:Transfer)-[:FROM_CLUB]-(from:Club), (t)-[:OF_PLAYER]->(player:Player)
WHERE to.country = "England" AND from.country = "England" AND player.nationality = "England"
RETURN player.name, from.name, to.name, t.numericFee, t.season
ORDER BY t.numericFee DESC
LIMIT 10
101. SELECT players.name, clubFrom.name, clubTo.name, t."numericFee", t.season
FROM transfers AS t
JOIN clubs AS clubFrom ON t.from_club_id = clubFrom.id
JOIN clubs AS clubTo ON t.to_club_id = clubTo.id
JOIN players ON t.player_id = players.id
JOIN countries AS fromCount ON clubFrom.country_id = fromCount.code
JOIN countries AS toCount ON clubTo.country_id = toCount.code
JOIN countries AS playerCount ON players.country_id = playerCount.code
WHERE fromCount.name = 'England' AND toCount.name = 'England' AND playerCount.name = 'England'
ORDER BY t."numericFee" DESC
LIMIT 10
MATCH (to:Club)<-[:TO_CLUB]-(t:Transfer)-[:FROM_CLUB]-(from:Club), (t)-[:OF_PLAYER]->(player:Player),
(player)-[:PLAYS_FOR]->(country:Country), (to)-[:PART_OF]->(country)<-[:PART_OF]-(from)
WHERE country.name = "England"
RETURN player.name, from.name, to.name, t.numericFee, t.season
ORDER BY t.numericFee DESC
LIMIT 10
102. SELECT players.name, clubFrom.name, clubTo.name, t."numericFee", t.season
FROM transfers AS t
JOIN clubs AS clubFrom ON t.from_club_id = clubFrom.id
JOIN clubs AS clubTo ON t.to_club_id = clubTo.id
JOIN players ON t.player_id = players.id
JOIN countries AS fromCount ON clubFrom.country_id = fromCount.code
JOIN countries AS toCount ON clubTo.country_id = toCount.code
JOIN countries AS playerCount ON players.country_id = playerCount.code
WHERE fromCount.name = 'England' AND toCount.name = 'England' AND playerCount.name = 'England'
ORDER BY t."numericFee" DESC
LIMIT 10
MATCH (to:Club)<-[:TO_CLUB]-(t:Transfer)-[:FROM_CLUB]-(from:Club), (t)-[:OF_PLAYER]->(player:Player),
(player)-[:PLAYS_FOR]->(country:Country), (to)-[:PART_OF]->(country)<-[:PART_OF]-(from)
WHERE country.name = "England"
RETURN player.name, from.name, to.name, t.numericFee, t.season
ORDER BY t.numericFee DESC
LIMIT 10
103. SELECT players.name, clubFrom.name, clubTo.name, t."numericFee", t.season
FROM transfers AS t
JOIN clubs AS clubFrom ON t.from_club_id = clubFrom.id
JOIN clubs AS clubTo ON t.to_club_id = clubTo.id
JOIN players ON t.player_id = players.id
JOIN countries AS fromCount ON clubFrom.country_id = fromCount.code
JOIN countries AS toCount ON clubTo.country_id = toCount.code
JOIN countries AS playerCount ON players.country_id = playerCount.code
WHERE fromCount.name = 'England' AND toCount.name = 'England' AND playerCount.name = 'England'
ORDER BY t."numericFee" DESC
LIMIT 10
MATCH (to:Club)<-[:TO_CLUB]-(t:Transfer)-[:FROM_CLUB]-(from:Club), (t)-[:OF_PLAYER]->(player:Player),
(player)-[:PLAYS_FOR]->(country:Country), (to)-[:PART_OF]->(country)<-[:PART_OF]-(from)
WHERE country.name = "England"
RETURN player.name, from.name, to.name, t.numericFee, t.season
ORDER BY t.numericFee DESC
LIMIT 10
104.
105. SELECT * FROM transfers AS t
JOIN clubs AS clubFrom ON t.from_club_id = clubFrom.id
JOIN clubs AS clubTo ON t.to_club_id = clubTo.id
JOIN players ON t.player_id = players.id
JOIN countries AS fromCountry ON clubFrom.country_id = fromCountry.code
JOIN countries AS toCountry ON clubTo.country_id = toCountry.code
JOIN confederations AS fromConfederation ON fromCountry.federation = fromConfederation.id
JOIN confederations AS toConfederation ON toCountry.federation = toConfederation.id
WHERE fromConfederation.id = 'afc' AND toConfederation.id = 'uefa'
ORDER BY t."numericFee" DESC
LIMIT 10
MATCH (to:Club)<-[:TO_CLUB]-(t:Transfer)-[:FROM_CLUB]-(from:Club), (t)-[:OF_PLAYER]->(player:Player),
(from)-[:PART_OF*2]->(:Confederation {id: "afc"}),
(to)-[:PART_OF*2]->(:Confederation {id: "uefa"})
RETURN player.name, from.name, to.name, t.numericFee, t.season
ORDER BY t.numericFee DESC
LIMIT 10
106. SELECT * FROM transfers AS t
JOIN clubs AS clubFrom ON t.from_club_id = clubFrom.id
JOIN clubs AS clubTo ON t.to_club_id = clubTo.id
JOIN players ON t.player_id = players.id
JOIN countries AS fromCountry ON clubFrom.country_id = fromCountry.code
JOIN countries AS toCountry ON clubTo.country_id = toCountry.code
JOIN confederations AS fromConfederation ON fromCountry.federation = fromConfederation.id
JOIN confederations AS toConfederation ON toCountry.federation = toConfederation.id
WHERE fromConfederation.id = 'afc' AND toConfederation.id = 'uefa'
ORDER BY t."numericFee" DESC
LIMIT 10
MATCH (to:Club)<-[:TO_CLUB]-(t:Transfer)-[:FROM_CLUB]-(from:Club), (t)-[:OF_PLAYER]->(player:Player),
(from)-[:PART_OF*2]->(:Confederation {id: "afc"}),
(to)-[:PART_OF*2]->(:Confederation {id: "uefa"})
RETURN player.name, from.name, to.name, t.numericFee, t.season
ORDER BY t.numericFee DESC
LIMIT 10
107.
108.
109. # dt
List of relations
Schema | Name | Type | Owner
--------+----------------+-------+-------------
public | clubs | table | markneedham
public | confederations | table | markneedham
public | countries | table | markneedham
public | players | table | markneedham
public | transfers | table | markneedham
(5 rows)
120. # SELECT * FROM clubs where country_id is null;
id | name | country | country_id
---------------------------------------+-------------------------+---------------+------------
/unknown/startseite/verein/75 | Unknown | |
/pohang/startseite/verein/311 | Pohang Steelers | Korea, South |
/bluewings/startseite/verein/3301 | Suwon Samsung Bluewings | Korea, South |
/ulsan/startseite/verein/3535 | Ulsan Hyundai | Korea, South |
/africa-sports/startseite/verein/2936 | Africa Sports | Cote d'Ivoire |
/monaco/startseite/verein/162 | AS Monaco | Monaco |
/jeonbuk/startseite/verein/6502 | Jeonbuk Hyundai Motors | Korea, South |
/busan/startseite/verein/2582 | Busan IPark | Korea, South |
(8 rows)
121. MATCH (club:Club)
WHERE NOT (club)-[:PART_OF]->()
RETURN club
+=====================================================================+
|club |
+=====================================================================+
|{name: Unknown, id: /unknown/startseite/verein/75} |
+---------------------------------------------------------------------+
|{country: Monaco, name: AS Monaco, id: /monaco/startseite/verein/162}|
+---------------------------------------------------------------------+
122. # drop table countries;
ERROR: cannot drop table countries because other objects depend
on it
DETAIL: constraint playersfk on table players depends on table
countries
HINT: Use DROP ... CASCADE to drop the dependent objects too.