SlideShare a Scribd company logo
1 of 136
Download to read offline
Cypher for SQL Developers
Mark Needham
@markhneedham
mark@neo4j.com
Talk structure
ā€£ Introduce data set
ā€£ Modeling
ā€£ Import
ā€£ Data Integrity
ā€£ Queries
ā€£ Migration/Refactoring
ā€£ Query optimisation
Introducing our data set...
Exploring transfermarkt
Exploring transfermarkt
|---------+--------------------+-----------------------------------------+--------------------+------------|
| season | playerName | playerUri | playerPosition | playerAge |
|---------+--------------------+-----------------------------------------+--------------------+------------|
| 90/91 | Aldair | /aldair/profil/spieler/4151 | Centre Back | 24 |
| 90/91 | Thomas HƤƟler | /thomas-hassler/profil/spieler/553 | Attacking Midfield | 24 |
| 90/91 | Roberto Baggio | /roberto-baggio/profil/spieler/4153 | Secondary Striker | 23 |
| 90/91 | Karl-Heinz Riedle | /karl-heinz-riedle/profil/spieler/13806 | Centre Forward | 24 |
| 90/91 | Henrik Larsen | /henrik-larsen/profil/spieler/101330 | Attacking Midfield | 24 |
| 90/91 | Gheorghe Hagi | /gheorghe-hagi/profil/spieler/7939 | Attacking Midfield | 25 |
| 90/91 | Hristo Stoichkov | /hristo-stoichkov/profil/spieler/7938 | Left Wing | 24 |
| 90/91 | Brian Laudrup | /brian-laudrup/profil/spieler/39667 | Centre Forward | 21 |
| 90/91 | Miguel Ɓngel Nadal | /miguel-angel-nadal/profil/spieler/7676 | Centre Back | 23 |
|---------+--------------------+-----------------------------------------+--------------------+------------|
Exploring transfermarkt
|-------------------+---------------------+-------------------------------------+--------------------|
| sellerClubName | sellerClubNameShort | sellerClubUri | sellerClubCountry |
|-------------------+---------------------+-------------------------------------+--------------------|
| SL Benfica | Benfica | /benfica/startseite/verein/294 | Portugal |
| 1. FC Kƶln | 1. FC Kƶln | /1-fc-koln/startseite/verein/3 | Germany |
| ACF Fiorentina | Fiorentina | /fiorentina/startseite/verein/430 | Italy |
| SV Werder Bremen | Werder Bremen | /werder-bremen/startseite/verein/86 | Germany |
| Lyngby BK | Lyngby BK | /lyngby-bk/startseite/verein/369 | Denmark |
| Steaua Bucharest | Steaua | /steaua/startseite/verein/301 | Romania |
| CSKA Sofia | CSKA Sofia | /cska-sofia/startseite/verein/208 | Bulgaria |
| KFC Uerdingen 05 | KFC Uerdingen | /kfc-uerdingen/startseite/verein/95 | Germany |
| RCD Mallorca | RCD Mallorca | /rcd-mallorca/startseite/verein/237 | Spain |
|-------------------+---------------------+-------------------------------------+--------------------|
Exploring transfermarkt
|----------------+--------------------+-------------------------------------+-------------------|
| buyerClubName | buyerClubNameShort | buyerClubUri | buyerClubCountry |
|----------------+--------------------+-------------------------------------+-------------------|
| AS Roma | AS Roma | /as-roma/startseite/verein/12 | Italy |
| Juventus FC | Juventus | /juventus/startseite/verein/506 | Italy |
| Juventus FC | Juventus | /juventus/startseite/verein/506 | Italy |
| SS Lazio | Lazio | /lazio/startseite/verein/398 | Italy |
| AC Pisa 1909 | AC Pisa | /ac-pisa/startseite/verein/4172 | Italy |
| Real Madrid | Real Madrid | /real-madrid/startseite/verein/418 | Spain |
| FC Barcelona | FC Barcelona | /fc-barcelona/startseite/verein/131 | Spain |
| Bayern Munich | Bayern Munich | /bayern-munich/startseite/verein/27 | Germany |
| FC Barcelona | FC Barcelona | /fc-barcelona/startseite/verein/131 | Spain |
|----------------+--------------------+-------------------------------------+-------------------|
Exploring transfermarkt
|--------------------------------------------------------+-------------+---------------|
| transferUri | transferFee | transferRank |
|--------------------------------------------------------+-------------+---------------|
| /jumplist/transfers/spieler/4151/transfer_id/6993 | Ā£6.75m | 1 |
| /jumplist/transfers/spieler/553/transfer_id/2405 | Ā£5.85m | 2 |
| /jumplist/transfers/spieler/4153/transfer_id/84533 | Ā£5.81m | 3 |
| /jumplist/transfers/spieler/13806/transfer_id/19054 | Ā£5.63m | 4 |
| /jumplist/transfers/spieler/101330/transfer_id/275067 | Ā£5.03m | 5 |
| /jumplist/transfers/spieler/7939/transfer_id/19343 | Ā£3.23m | 6 |
| /jumplist/transfers/spieler/7938/transfer_id/11563 | Ā£2.25m | 7 |
| /jumplist/transfers/spieler/39667/transfer_id/90285 | Ā£2.25m | 8 |
| /jumplist/transfers/spieler/7676/transfer_id/11828 | Ā£2.10m | 9 |
|--------------------------------------------------------+-------------+---------------|
Relational Model
players
id
name
position
clubs
id
name
country
transfers
id
fee
player_age
player_id
from_club_id
to_club_id
season
Graph model
Nodes
Relationships
Properties
Labels
Relational vs Graph
Records
in tables
Nodes
"Soft"
relationships
computed at
query time
"Hard"
relationships
built into the
data store
Relational Import
Create players table
CREATE TABLE players (
"id" character varying(100)
NOT NULL PRIMARY KEY,
"name" character varying(150) NOT NULL,
"position" character varying(20)
);
Insert players
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');
Create clubs table
CREATE TABLE clubs (
"id" character varying(100)
NOT NULL PRIMARY KEY,
"name" character varying(50) NOT NULL,
"country" character varying(50)
);
Insert clubs
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');
Create transfers table
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)
);
Insert transfers
INSERT INTO transfers VALUES('/jumplist/transfers/spieler/4151/transfer_id/6993',
'Ā£6.75m', 6750000, '90/91', 24, '/aldair/profil/spieler/4151',
'/benfica/startseite/verein/294', '/as-roma/startseite/verein/12');
INSERT INTO transfers VALUES('/jumplist/transfers/spieler/553/transfer_id/2405',
'Ā£5.85m', 5850000, '90/91', 24, '/thomas-hassler/profil/spieler/553', '/1-fc-
koln/startseite/verein/3', '/juventus/startseite/verein/506');
INSERT INTO transfers VALUES('/jumplist/transfers/spieler/4153/transfer_id/84533',
'Ā£5.81m', 5810000, '90/91', 23, '/roberto-baggio/profil/spieler/4153',
'/fiorentina/startseite/verein/430', '/juventus/startseite/verein/506');
Graph Import
LOAD CSV
ā€£ Tool for importing CSV files
ā€£ Intended for data sets of ~10M records
ā€£ Works against live database
ā€£ Use Cypher constructs to define graph
LOAD CSV
[USING PERIODIC COMMIT [1000]]
LOAD CSV WITH HEADERS FROM "(file|http)://" AS row
MATCH (:Label {property: row.header})
CREATE (:Label {property: row.header})
MERGE (:Label {property: row.header})
LOAD CSV
[USING PERIODIC COMMIT [1000]]
LOAD CSV WITH HEADERS FROM "(file|http)://" AS row
MATCH (:Label {property: row.header})
CREATE (:Label {property: row.header})
MERGE (:Label {property: row.header})
LOAD CSV
[USING PERIODIC COMMIT [1000]]
LOAD CSV WITH HEADERS FROM "(file|http)://" AS row
MATCH (:Label {property: row.header})
CREATE (:Label {property: row.header})
MERGE (:Label {property: row.header})
LOAD CSV
[USING PERIODIC COMMIT [1000]]
LOAD CSV WITH HEADERS FROM "(file|http)://" AS row
MATCH (:Label {property: row.header})
CREATE (:Label {property: row.header})
MERGE (:Label {property: row.header})
LOAD CSV
[USING PERIODIC COMMIT [1000]]
LOAD CSV WITH HEADERS FROM "(file|http)://" AS row
MATCH (:Label {property: row.header})
CREATE (:Label {property: row.header})
MERGE (:Label {property: row.header})
LOAD CSV
[USING PERIODIC COMMIT [1000]]
LOAD CSV WITH HEADERS FROM "(file|http)://" AS row
MATCH (:Label {property: row.header})
CREATE (:Label {property: row.header})
MERGE (:Label {property: row.header})
Exploring the data
LOAD CSV WITH HEADERS
FROM "file:///transfers.csv"
AS row
RETURN COUNT(*)
Exploring the data
LOAD CSV WITH HEADERS
FROM "file:///transfers.csv"
AS row
RETURN COUNT(*)
Exploring the data
LOAD CSV WITH HEADERS
FROM "file:///transfers.csv"
AS row
RETURN row
LIMIT 1
Exploring the data
LOAD CSV WITH HEADERS
FROM "file:///transfers.csv"
AS row
RETURN row
LIMIT 1
Import players
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///transfers.csv" AS row
CREATE (player:Player {
id: row.playerUri,
name: row.playerName,
position: row.playerPosition
})
Import players
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///transfers.csv" AS row
CREATE (player:Player {
id: row.playerUri,
name: row.playerName,
position: row.playerPosition
})
Not so fast!
Ensure uniqueness of players
CREATE CONSTRAINT ON (player:Player)
ASSERT player.id IS UNIQUE
Import players
USING PERIODIC COMMIT
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]
Import players
USING PERIODIC COMMIT
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
Import clubs
CREATE CONSTRAINT ON (club:Club)
ASSERT club.id IS UNIQUE
Import selling clubs
USING PERIODIC COMMIT
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
Import buying clubs
USING PERIODIC COMMIT
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
Import transfers
CREATE CONSTRAINT ON (transfer:Transfer)
ASSERT transfer.id IS UNIQUE
Import transfers
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)
Schema
Optional Schema
ā€£ Unique node property constraint
Optional Schema
ā€£ Unique node property constraint
CREATE CONSTRAINT ON (club:Club)
ASSERT club.id IS UNIQUE
Optional Schema
ā€£ Unique node property constraint
ā€£ Node property existence constraint
Optional Schema
ā€£ Unique node property constraint
ā€£ Node property existence constraint
CREATE CONSTRAINT ON (club:Club)
ASSERT EXISTS(club.name)
Optional Schema
ā€£ Unique node property constraint
ā€£ Node property existence constraint
ā€£ Relationship property existence constraint
Optional Schema
ā€£ Unique node property constraint
ā€£ Node property existence constraint
ā€£ Relationship property existence constraint
CREATE CONSTRAINT ON ()-[player:OF_PLAYER]-()
ASSERT exists(player.age)
SQL vs Cypher
Find player by name
SELECT *
FROM players
WHERE players.name = 'Cristiano Ronaldo'
SELECT *
FROM players
WHERE players.name = 'Cristiano Ronaldo'
MATCH (player:Player { name: "Cristiano Ronaldo" })
RETURN player
SELECT *
FROM players
WHERE players.name = 'Cristiano Ronaldo'
MATCH (player:Player { name: "Cristiano Ronaldo" })
RETURN player
SELECT *
FROM players
WHERE players.name = 'Cristiano Ronaldo'
MATCH (player:Player { name: "Cristiano Ronaldo" })
RETURN player
Find transfers between
clubs
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'
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
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
How does Neo4j use indexes?
Indexes are only used to find the starting
point for queries.
Use index scans to look up
rows in tables and join them
with rows from other tables
Use indexes to find the starting
points for a query.
Relational
Graph
How does Neo4j use indexes?
Migrating/refactoring
the model
Player nationality
|------------------------------------------+--------------------+--------------------|
| playerUri | playerName | playerNationality |
|------------------------------------------+--------------------+--------------------|
| /aldair/profil/spieler/4151 | Aldair | Brazil |
| /thomas-hassler/profil/spieler/553 | Thomas HƤƟler | Germany |
| /roberto-baggio/profil/spieler/4153 | Roberto Baggio | Italy |
| /karl-heinz-riedle/profil/spieler/13806 | Karl-Heinz Riedle | Germany |
| /henrik-larsen/profil/spieler/101330 | Henrik Larsen | Denmark |
| /gheorghe-hagi/profil/spieler/7939 | Gheorghe Hagi | Romania |
| /hristo-stoichkov/profil/spieler/7938 | Hristo Stoichkov | Bulgaria |
| /brian-laudrup/profil/spieler/39667 | Brian Laudrup | Denmark |
| /miguel-angel-nadal/profil/spieler/7676 | Miguel Ɓngel Nadal | Spain |
|------------------------------------------+--------------------+--------------------|
Relational migration
Relational Model
players
id
name
position
nationality
clubs
id
name
country
transfers
id
fee
player_age
player_id
from_club_id
to_club_id
season
Add column to players table
ALTER TABLE players
ADD COLUMN nationality varying(30);
Update players table
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';
Graph refactoring
Graph model
Add property to player nodes
USING PERIODIC COMMIT
LOAD CSV WITH HEADERS FROM "file:///transfers.csv" AS row
MATCH (player:Player {id: row.playerUri})
SET player.nationality = row.playerNationality
Find transfers of English
players
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
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
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
Countries and confederations
|----------------------+----------------|
| 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 |
|-----------+-----------+-------------------------------------------------|
Relational migration
Relational Model
players
id
name
position
country_id
clubs
id
name
country_id
transfers
id
fee
player_age
player_id
from_club_id
to_club_id
season
countries
id
name
confederation_id
confederations
id
shortName
name
region
Create confederations table
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
);
Populate confederations
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');
Create countries table
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)
);
Populate countries
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');
Add column to clubs table
ALTER TABLE clubs
ADD COLUMN country_id character varying(3)
REFERENCES countries(code);
Update clubs
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;
Update clubs
# 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)
Remove country
ALTER TABLE clubs
DROP COLUMN country;
Add column to players table
ALTER TABLE players
ADD COLUMN country_id character varying(3)
REFERENCES countries(code);
Update players
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;
Update players
# 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)
Remove nationality
ALTER TABLE players
DROP COLUMN nationality;
Graph refactoring
Graph model
Import confederations
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
Import countries
LOAD CSV WITH HEADERS FROM "file:///countries.csv"
AS row
MERGE (country:Country {id: row.countryCode})
ON CREATE SET country.name = row.country
WITH country, row
MATCH (conf:Confederation {id: row.confederation })
MERGE (country)-[:PART_OF]->(conf)
Refactor clubs
MATCH (club:Club)
MATCH (country:Country {name: club.country})
MERGE (club)-[:PART_OF]->(country)
REMOVE club.country
Refactor players
MATCH (player:Player)
MATCH (country:Country {name: player.nationality})
MERGE (player)-[:PLAYS_FOR]->(country)
REMOVE player.nationality
Recap: Find transfers of
English players
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
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)-[: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
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)-[: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
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)-[: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
Find transfers between
different confederations
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
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
Whatā€™s in my database?
Tables
# 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)
Node labels
CALL db.labels()
+=============+
|label |
+=============+
|Player |
+-------------+
|Club |
+-------------+
|Transfer |
+-------------+
|Loan |
+-------------+
|Confederation|
+-------------+
|Country |
+-------------+
Node labels
Table schema
# d+ countries
Table "public.countries"
Column | Type | Modifiers | Storage | Stats target | Description
------------+-----------------------+-----------+----------+--------------+-------------
code | character varying(3) | not null | extended | |
name | character varying(50) | not null | extended | |
federation | character varying(10) | not null | extended | |
Indexes:
"pk_countries" PRIMARY KEY, btree (code)
Foreign-key constraints:
"countries_federation_fkey" FOREIGN KEY (federation) REFERENCES confederations(id)
Referenced by:
TABLE "players" CONSTRAINT "playersfk" FOREIGN KEY (country_id) REFERENCES countries(code) MATCH FULL
:schema
Indexes
ON :Club(name) ONLINE
ON :Club(id) ONLINE (for uniqueness constraint)
ON :Player(name) ONLINE
ON :Player(id) ONLINE (for uniqueness constraint)
Constraints
ON (player:Player) ASSERT player.id IS UNIQUE
ON (club:Club) ASSERT exists(club.name)
ON (club:Club) ASSERT club.id IS UNIQUE
ON ()-[of_player:OF_PLAYER]-() ASSERT exists(of_player.age)
Graph schema
MATCH (country:Country)
RETURN keys(country), COUNT(*) AS times
+-----------------------+
| keys(country) | times |
+-----------------------+
| ["id","name"] | 198 |
+-----------------------+
Graph schema
Graph schema
MATCH (club:Club)
RETURN keys(club), COUNT(*) AS times
+---------------------------------+
| keys(club) | times |
+---------------------------------+
| ["id","name"] | 806 |
| ["name","country","id"] | 1 |
+---------------------------------+
Entity/Relationship diagram
Meta graph
Meta graph
MATCH (a)-[r]->(b)
WITH head(labels(a)) AS l,
head(labels(b)) AS l2, type(r) AS rel_type,
count(*) as count
CALL apoc.create.vNode([l],{name:l}) yield node as a
CALL apoc.create.vNode([l2],{name:l2}) yield node as b
CALL apoc.create.vRelationship(a,rel_type,{name:rel_type, count:count},b)
YIELD rel
RETURN *;
Data Integrity
Clubs without country
# 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)
Clubs without country
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}|
+---------------------------------------------------------------------+
Deleting data - SQL
# 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.
MATCH (country:Country)
DELETE country
org.neo4j.kernel.api.exceptions.TransactionFailureException: Node
record Node[11306,used=false,rel=24095,prop=-1,labels=Inline(0x0:
[]),light] still has relationships
Deleting data - Cypher
MATCH (country:Country)
DETACH DELETE country
Deleted 198 nodes, deleted 5071 relationships, statement executed
in 498 ms.
Deleting data - Cypher
Query Optimisation
Optimising queries
ā€£ Use EXPLAIN/PROFILE to see what your
queries are doing under the covers
ā€£ Index the starting points of queries
ā€£ Reduce work in progress of intermediate
parts of the query where possible
ā€£ Look at the warnings in the Neo4j browser -
they are often helpful!
Optimising queries - useful links
ā€£ Tuning Your Cypher
https://www.youtube.com/watch?v=tYtyoYcd_e8
ā€£ Neo4j 2.2 Query Tuning
http://neo4j.com/blog/neo4j-2-2-query-tuning/
ā€£ Ask for help on Stack Overflow/Neo4j Slack
http://neo4j-users-slack-invite.herokuapp.com
One more thing...
ā€£ New in Neo4j 3.0.0!
Procedures
ā€£ New in Neo4j 3.0.0!
ā€£ Weā€™ve already seen an example!
CALL db.labels()
ā€£ Michael Hunger has created a set of
procedures (APOC) at:
https://github.com/jexp/neo4j-apoc-procedures
Procedures
WITH "https://api.github.com/search/repositories?q=neo4j"
AS githubUri
CALL apoc.load.json(githubUri)
YIELD value AS document
UNWIND document.items AS item
RETURN item.full_name, item.watchers_count, item.forks
ORDER BY item.forks DESC
Querying github
WITH "https://api.github.com/search/repositories?q=neo4j"
AS githubUri
CALL apoc.load.json(githubUri)
YIELD value AS document
UNWIND document.items AS item
RETURN item.full_name, item.watchers_count, item.forks
ORDER BY item.forks DESC
Querying github
+------------------------------------------------------------------------+
| item.full_name | item.watchers_count | item.forks |
+------------------------------------------------------------------------+
| "neo4j/neo4j" | 2472 | 872 |
| "spring-projects/spring-data-neo4j" | 403 | 476 |
| "neo4j-contrib/developer-resources" | 106 | 295 |
| "neo4jrb/neo4j" | 1014 | 190 |
| "jadell/neo4jphp" | 507 | 140 |
| "thingdom/node-neo4j" | 780 | 127 |
| "aseemk/node-neo4j-template" | 176 | 91 |
| "jimwebber/neo4j-tutorial" | 268 | 87 |
| "rickardoberg/neo4j-jdbc" | 33 | 68 |
| "FaKod/neo4j-scala" | 194 | 64 |
+------------------------------------------------------------------------+
Querying github
Questions? :-)
Mark Needham
mark@neo4j.com
@markhneedham
https://github.com/neo4j-meetups/cypher-for-sql-developers

More Related Content

Similar to Intro to Cypher for the SQL Developer

Neo4j: Import and Data Modelling
Neo4j: Import and Data ModellingNeo4j: Import and Data Modelling
Neo4j: Import and Data ModellingNeo4j
Ā 
SDKs, the good the bad the ugly - Japan
SDKs, the good the bad the ugly - JapanSDKs, the good the bad the ugly - Japan
SDKs, the good the bad the ugly - Japantristansokol
Ā 
Informix Warehouse Accelerator (IWA) features in version 12.1
Informix Warehouse Accelerator (IWA) features in version 12.1Informix Warehouse Accelerator (IWA) features in version 12.1
Informix Warehouse Accelerator (IWA) features in version 12.1Keshav Murthy
Ā 
Date difference[1]
Date difference[1]Date difference[1]
Date difference[1]shafiullas
Ā 
Real Time Health Analytics With WebSockets Python 3 and Redis PubSub: Benjami...
Real Time Health Analytics With WebSockets Python 3 and Redis PubSub: Benjami...Real Time Health Analytics With WebSockets Python 3 and Redis PubSub: Benjami...
Real Time Health Analytics With WebSockets Python 3 and Redis PubSub: Benjami...Redis Labs
Ā 
ģŠ¤ķ¬ė¦½ķŠøė”œ Aws ģ„œė¹„ģŠ¤ ģžė™ķ™” ķ•˜źø° 20161121 slideshare
ģŠ¤ķ¬ė¦½ķŠøė”œ Aws ģ„œė¹„ģŠ¤ ģžė™ķ™” ķ•˜źø° 20161121 slideshareģŠ¤ķ¬ė¦½ķŠøė”œ Aws ģ„œė¹„ģŠ¤ ģžė™ķ™” ķ•˜źø° 20161121 slideshare
ģŠ¤ķ¬ė¦½ķŠøė”œ Aws ģ„œė¹„ģŠ¤ ģžė™ķ™” ķ•˜źø° 20161121 slideshareIn Chul Shin
Ā 
Database Development Replication Security Maintenance Report
Database Development Replication Security Maintenance ReportDatabase Development Replication Security Maintenance Report
Database Development Replication Security Maintenance Reportnyin27
Ā 
Cassandra, web scale no sql data platform
Cassandra, web scale no sql data platformCassandra, web scale no sql data platform
Cassandra, web scale no sql data platformMarko Å valjek
Ā 
Streaming Operational Data with MariaDB MaxScale
Streaming Operational Data with MariaDB MaxScaleStreaming Operational Data with MariaDB MaxScale
Streaming Operational Data with MariaDB MaxScaleMariaDB plc
Ā 
Windowing Functions - Little Rock Tech Fest 2019
Windowing Functions - Little Rock Tech Fest 2019Windowing Functions - Little Rock Tech Fest 2019
Windowing Functions - Little Rock Tech Fest 2019Dave Stokes
Ā 
Windowing Functions - Little Rock Tech fest 2019
Windowing Functions - Little Rock Tech fest 2019Windowing Functions - Little Rock Tech fest 2019
Windowing Functions - Little Rock Tech fest 2019Dave Stokes
Ā 
ELK Stack - Turn boring logfiles into sexy dashboard
ELK Stack - Turn boring logfiles into sexy dashboardELK Stack - Turn boring logfiles into sexy dashboard
ELK Stack - Turn boring logfiles into sexy dashboardGeorg Sorst
Ā 
The Current State of Table API in 2022
The Current State of Table API in 2022The Current State of Table API in 2022
The Current State of Table API in 2022Flink Forward
Ā 
Extending spark ML for custom models now with python!
Extending spark ML for custom models  now with python!Extending spark ML for custom models  now with python!
Extending spark ML for custom models now with python!Holden Karau
Ā 
Ct es past_present_future_nycpgday_20130322
Ct es past_present_future_nycpgday_20130322Ct es past_present_future_nycpgday_20130322
Ct es past_present_future_nycpgday_20130322David Fetter
Ā 
KSQL - Stream Processing simplified!
KSQL - Stream Processing simplified!KSQL - Stream Processing simplified!
KSQL - Stream Processing simplified!Guido Schmutz
Ā 
Using Optimizer Hints to Improve MySQL Query Performance
Using Optimizer Hints to Improve MySQL Query PerformanceUsing Optimizer Hints to Improve MySQL Query Performance
Using Optimizer Hints to Improve MySQL Query Performanceoysteing
Ā 
All you need to know about CREATE STATISTICS
All you need to know about CREATE STATISTICSAll you need to know about CREATE STATISTICS
All you need to know about CREATE STATISTICSEDB
Ā 
Everything That Is Really Useful in Oracle Database 12c for Application Devel...
Everything That Is Really Useful in Oracle Database 12c for Application Devel...Everything That Is Really Useful in Oracle Database 12c for Application Devel...
Everything That Is Really Useful in Oracle Database 12c for Application Devel...Lucas Jellema
Ā 

Similar to Intro to Cypher for the SQL Developer (20)

Neo4j: Import and Data Modelling
Neo4j: Import and Data ModellingNeo4j: Import and Data Modelling
Neo4j: Import and Data Modelling
Ā 
SDKs, the good the bad the ugly - Japan
SDKs, the good the bad the ugly - JapanSDKs, the good the bad the ugly - Japan
SDKs, the good the bad the ugly - Japan
Ā 
Informix Warehouse Accelerator (IWA) features in version 12.1
Informix Warehouse Accelerator (IWA) features in version 12.1Informix Warehouse Accelerator (IWA) features in version 12.1
Informix Warehouse Accelerator (IWA) features in version 12.1
Ā 
Date difference[1]
Date difference[1]Date difference[1]
Date difference[1]
Ā 
Real Time Health Analytics With WebSockets Python 3 and Redis PubSub: Benjami...
Real Time Health Analytics With WebSockets Python 3 and Redis PubSub: Benjami...Real Time Health Analytics With WebSockets Python 3 and Redis PubSub: Benjami...
Real Time Health Analytics With WebSockets Python 3 and Redis PubSub: Benjami...
Ā 
ģŠ¤ķ¬ė¦½ķŠøė”œ Aws ģ„œė¹„ģŠ¤ ģžė™ķ™” ķ•˜źø° 20161121 slideshare
ģŠ¤ķ¬ė¦½ķŠøė”œ Aws ģ„œė¹„ģŠ¤ ģžė™ķ™” ķ•˜źø° 20161121 slideshareģŠ¤ķ¬ė¦½ķŠøė”œ Aws ģ„œė¹„ģŠ¤ ģžė™ķ™” ķ•˜źø° 20161121 slideshare
ģŠ¤ķ¬ė¦½ķŠøė”œ Aws ģ„œė¹„ģŠ¤ ģžė™ķ™” ķ•˜źø° 20161121 slideshare
Ā 
Database Development Replication Security Maintenance Report
Database Development Replication Security Maintenance ReportDatabase Development Replication Security Maintenance Report
Database Development Replication Security Maintenance Report
Ā 
Cassandra, web scale no sql data platform
Cassandra, web scale no sql data platformCassandra, web scale no sql data platform
Cassandra, web scale no sql data platform
Ā 
Streaming Operational Data with MariaDB MaxScale
Streaming Operational Data with MariaDB MaxScaleStreaming Operational Data with MariaDB MaxScale
Streaming Operational Data with MariaDB MaxScale
Ā 
Windowing Functions - Little Rock Tech Fest 2019
Windowing Functions - Little Rock Tech Fest 2019Windowing Functions - Little Rock Tech Fest 2019
Windowing Functions - Little Rock Tech Fest 2019
Ā 
Windowing Functions - Little Rock Tech fest 2019
Windowing Functions - Little Rock Tech fest 2019Windowing Functions - Little Rock Tech fest 2019
Windowing Functions - Little Rock Tech fest 2019
Ā 
ELK Stack - Turn boring logfiles into sexy dashboard
ELK Stack - Turn boring logfiles into sexy dashboardELK Stack - Turn boring logfiles into sexy dashboard
ELK Stack - Turn boring logfiles into sexy dashboard
Ā 
The Current State of Table API in 2022
The Current State of Table API in 2022The Current State of Table API in 2022
The Current State of Table API in 2022
Ā 
MySQL SQL Tutorial
MySQL SQL TutorialMySQL SQL Tutorial
MySQL SQL Tutorial
Ā 
Extending spark ML for custom models now with python!
Extending spark ML for custom models  now with python!Extending spark ML for custom models  now with python!
Extending spark ML for custom models now with python!
Ā 
Ct es past_present_future_nycpgday_20130322
Ct es past_present_future_nycpgday_20130322Ct es past_present_future_nycpgday_20130322
Ct es past_present_future_nycpgday_20130322
Ā 
KSQL - Stream Processing simplified!
KSQL - Stream Processing simplified!KSQL - Stream Processing simplified!
KSQL - Stream Processing simplified!
Ā 
Using Optimizer Hints to Improve MySQL Query Performance
Using Optimizer Hints to Improve MySQL Query PerformanceUsing Optimizer Hints to Improve MySQL Query Performance
Using Optimizer Hints to Improve MySQL Query Performance
Ā 
All you need to know about CREATE STATISTICS
All you need to know about CREATE STATISTICSAll you need to know about CREATE STATISTICS
All you need to know about CREATE STATISTICS
Ā 
Everything That Is Really Useful in Oracle Database 12c for Application Devel...
Everything That Is Really Useful in Oracle Database 12c for Application Devel...Everything That Is Really Useful in Oracle Database 12c for Application Devel...
Everything That Is Really Useful in Oracle Database 12c for Application Devel...
Ā 

More from Neo4j

Your enemies use GenAI too - staying ahead of fraud with Neo4j
Your enemies use GenAI too - staying ahead of fraud with Neo4jYour enemies use GenAI too - staying ahead of fraud with Neo4j
Your enemies use GenAI too - staying ahead of fraud with Neo4jNeo4j
Ā 
BT & Neo4j _ How Knowledge Graphs help BT deliver Digital Transformation.pptx
BT & Neo4j _ How Knowledge Graphs help BT deliver Digital Transformation.pptxBT & Neo4j _ How Knowledge Graphs help BT deliver Digital Transformation.pptx
BT & Neo4j _ How Knowledge Graphs help BT deliver Digital Transformation.pptxNeo4j
Ā 
Workshop: Enabling GenAI Breakthroughs with Knowledge Graphs - GraphSummit Milan
Workshop: Enabling GenAI Breakthroughs with Knowledge Graphs - GraphSummit MilanWorkshop: Enabling GenAI Breakthroughs with Knowledge Graphs - GraphSummit Milan
Workshop: Enabling GenAI Breakthroughs with Knowledge Graphs - GraphSummit MilanNeo4j
Ā 
Workshop - Architecting Innovative Graph Applications- GraphSummit Milan
Workshop -  Architecting Innovative Graph Applications- GraphSummit MilanWorkshop -  Architecting Innovative Graph Applications- GraphSummit Milan
Workshop - Architecting Innovative Graph Applications- GraphSummit MilanNeo4j
Ā 
LARUS - Galileo.XAI e Gen-AI: la nuova prospettiva di LARUS per il futuro del...
LARUS - Galileo.XAI e Gen-AI: la nuova prospettiva di LARUS per il futuro del...LARUS - Galileo.XAI e Gen-AI: la nuova prospettiva di LARUS per il futuro del...
LARUS - Galileo.XAI e Gen-AI: la nuova prospettiva di LARUS per il futuro del...Neo4j
Ā 
GraphSummit Milan - Visione e roadmap del prodotto Neo4j
GraphSummit Milan - Visione e roadmap del prodotto Neo4jGraphSummit Milan - Visione e roadmap del prodotto Neo4j
GraphSummit Milan - Visione e roadmap del prodotto Neo4jNeo4j
Ā 
GraphSummit Milan - Neo4j: The Art of the Possible with Graph
GraphSummit Milan - Neo4j: The Art of the Possible with GraphGraphSummit Milan - Neo4j: The Art of the Possible with Graph
GraphSummit Milan - Neo4j: The Art of the Possible with GraphNeo4j
Ā 
LARUS - Galileo.XAI e Gen-AI: la nuova prospettiva di LARUS per il futuro del...
LARUS - Galileo.XAI e Gen-AI: la nuova prospettiva di LARUS per il futuro del...LARUS - Galileo.XAI e Gen-AI: la nuova prospettiva di LARUS per il futuro del...
LARUS - Galileo.XAI e Gen-AI: la nuova prospettiva di LARUS per il futuro del...Neo4j
Ā 
UNI DI NAPOLI FEDERICO II - Il ruolo dei grafi nell'AI Conversazionale Ibrida
UNI DI NAPOLI FEDERICO II - Il ruolo dei grafi nell'AI Conversazionale IbridaUNI DI NAPOLI FEDERICO II - Il ruolo dei grafi nell'AI Conversazionale Ibrida
UNI DI NAPOLI FEDERICO II - Il ruolo dei grafi nell'AI Conversazionale IbridaNeo4j
Ā 
CERVED e Neo4j su una nuvola, migrazione ed evoluzione di un grafo mission cr...
CERVED e Neo4j su una nuvola, migrazione ed evoluzione di un grafo mission cr...CERVED e Neo4j su una nuvola, migrazione ed evoluzione di un grafo mission cr...
CERVED e Neo4j su una nuvola, migrazione ed evoluzione di un grafo mission cr...Neo4j
Ā 
From Knowledge Graphs via Lego Bricks to scientific conversations.pptx
From Knowledge Graphs via Lego Bricks to scientific conversations.pptxFrom Knowledge Graphs via Lego Bricks to scientific conversations.pptx
From Knowledge Graphs via Lego Bricks to scientific conversations.pptxNeo4j
Ā 
Novo Nordisk: When Knowledge Graphs meet LLMs
Novo Nordisk: When Knowledge Graphs meet LLMsNovo Nordisk: When Knowledge Graphs meet LLMs
Novo Nordisk: When Knowledge Graphs meet LLMsNeo4j
Ā 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
Ā 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
Ā 
QIAGEN: Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
QIAGEN: Biomedical Knowledge Graphs for Data Scientists and BioinformaticiansQIAGEN: Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
QIAGEN: Biomedical Knowledge Graphs for Data Scientists and BioinformaticiansNeo4j
Ā 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
Ā 
SIEMENS: RAPUNZEL ā€“ A Tale About Knowledge Graph
SIEMENS: RAPUNZEL ā€“ A Tale About Knowledge GraphSIEMENS: RAPUNZEL ā€“ A Tale About Knowledge Graph
SIEMENS: RAPUNZEL ā€“ A Tale About Knowledge GraphNeo4j
Ā 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Neo4j
Ā 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfNeo4j
Ā 
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...Neo4j
Ā 

More from Neo4j (20)

Your enemies use GenAI too - staying ahead of fraud with Neo4j
Your enemies use GenAI too - staying ahead of fraud with Neo4jYour enemies use GenAI too - staying ahead of fraud with Neo4j
Your enemies use GenAI too - staying ahead of fraud with Neo4j
Ā 
BT & Neo4j _ How Knowledge Graphs help BT deliver Digital Transformation.pptx
BT & Neo4j _ How Knowledge Graphs help BT deliver Digital Transformation.pptxBT & Neo4j _ How Knowledge Graphs help BT deliver Digital Transformation.pptx
BT & Neo4j _ How Knowledge Graphs help BT deliver Digital Transformation.pptx
Ā 
Workshop: Enabling GenAI Breakthroughs with Knowledge Graphs - GraphSummit Milan
Workshop: Enabling GenAI Breakthroughs with Knowledge Graphs - GraphSummit MilanWorkshop: Enabling GenAI Breakthroughs with Knowledge Graphs - GraphSummit Milan
Workshop: Enabling GenAI Breakthroughs with Knowledge Graphs - GraphSummit Milan
Ā 
Workshop - Architecting Innovative Graph Applications- GraphSummit Milan
Workshop -  Architecting Innovative Graph Applications- GraphSummit MilanWorkshop -  Architecting Innovative Graph Applications- GraphSummit Milan
Workshop - Architecting Innovative Graph Applications- GraphSummit Milan
Ā 
LARUS - Galileo.XAI e Gen-AI: la nuova prospettiva di LARUS per il futuro del...
LARUS - Galileo.XAI e Gen-AI: la nuova prospettiva di LARUS per il futuro del...LARUS - Galileo.XAI e Gen-AI: la nuova prospettiva di LARUS per il futuro del...
LARUS - Galileo.XAI e Gen-AI: la nuova prospettiva di LARUS per il futuro del...
Ā 
GraphSummit Milan - Visione e roadmap del prodotto Neo4j
GraphSummit Milan - Visione e roadmap del prodotto Neo4jGraphSummit Milan - Visione e roadmap del prodotto Neo4j
GraphSummit Milan - Visione e roadmap del prodotto Neo4j
Ā 
GraphSummit Milan - Neo4j: The Art of the Possible with Graph
GraphSummit Milan - Neo4j: The Art of the Possible with GraphGraphSummit Milan - Neo4j: The Art of the Possible with Graph
GraphSummit Milan - Neo4j: The Art of the Possible with Graph
Ā 
LARUS - Galileo.XAI e Gen-AI: la nuova prospettiva di LARUS per il futuro del...
LARUS - Galileo.XAI e Gen-AI: la nuova prospettiva di LARUS per il futuro del...LARUS - Galileo.XAI e Gen-AI: la nuova prospettiva di LARUS per il futuro del...
LARUS - Galileo.XAI e Gen-AI: la nuova prospettiva di LARUS per il futuro del...
Ā 
UNI DI NAPOLI FEDERICO II - Il ruolo dei grafi nell'AI Conversazionale Ibrida
UNI DI NAPOLI FEDERICO II - Il ruolo dei grafi nell'AI Conversazionale IbridaUNI DI NAPOLI FEDERICO II - Il ruolo dei grafi nell'AI Conversazionale Ibrida
UNI DI NAPOLI FEDERICO II - Il ruolo dei grafi nell'AI Conversazionale Ibrida
Ā 
CERVED e Neo4j su una nuvola, migrazione ed evoluzione di un grafo mission cr...
CERVED e Neo4j su una nuvola, migrazione ed evoluzione di un grafo mission cr...CERVED e Neo4j su una nuvola, migrazione ed evoluzione di un grafo mission cr...
CERVED e Neo4j su una nuvola, migrazione ed evoluzione di un grafo mission cr...
Ā 
From Knowledge Graphs via Lego Bricks to scientific conversations.pptx
From Knowledge Graphs via Lego Bricks to scientific conversations.pptxFrom Knowledge Graphs via Lego Bricks to scientific conversations.pptx
From Knowledge Graphs via Lego Bricks to scientific conversations.pptx
Ā 
Novo Nordisk: When Knowledge Graphs meet LLMs
Novo Nordisk: When Knowledge Graphs meet LLMsNovo Nordisk: When Knowledge Graphs meet LLMs
Novo Nordisk: When Knowledge Graphs meet LLMs
Ā 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Ā 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Ā 
QIAGEN: Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
QIAGEN: Biomedical Knowledge Graphs for Data Scientists and BioinformaticiansQIAGEN: Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
QIAGEN: Biomedical Knowledge Graphs for Data Scientists and Bioinformaticians
Ā 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
Ā 
SIEMENS: RAPUNZEL ā€“ A Tale About Knowledge Graph
SIEMENS: RAPUNZEL ā€“ A Tale About Knowledge GraphSIEMENS: RAPUNZEL ā€“ A Tale About Knowledge Graph
SIEMENS: RAPUNZEL ā€“ A Tale About Knowledge Graph
Ā 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024
Ā 
Connecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdfConnecting the Dots for Information Discovery.pdf
Connecting the Dots for Information Discovery.pdf
Ā 
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
ISDEFE - GraphSummit Madrid - ARETA: Aviation Real-Time Emissions Token Accre...
Ā 

Recently uploaded

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
Ā 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MIND CTI
Ā 
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...TrustArc
Ā 
JohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard37
Ā 
Simplifying Mobile A11y Presentation.pptx
Simplifying Mobile A11y Presentation.pptxSimplifying Mobile A11y Presentation.pptx
Simplifying Mobile A11y Presentation.pptxMarkSteadman7
Ā 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Victor Rentea
Ā 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdfSandro Moreira
Ā 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxRemote DBA Services
Ā 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Orbitshub
Ā 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamUiPathCommunity
Ā 
Introduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMIntroduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMKumar Satyam
Ā 
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)Samir Dash
Ā 
Quantum Leap in Next-Generation Computing
Quantum Leap in Next-Generation ComputingQuantum Leap in Next-Generation Computing
Quantum Leap in Next-Generation ComputingWSO2
Ā 
JavaScript Usage Statistics 2024 - The Ultimate Guide
JavaScript Usage Statistics 2024 - The Ultimate GuideJavaScript Usage Statistics 2024 - The Ultimate Guide
JavaScript Usage Statistics 2024 - The Ultimate GuidePixlogix Infotech
Ā 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingEdi Saputra
Ā 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfOrbitshub
Ā 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
Ā 
How to Check CNIC Information Online with Pakdata cf
How to Check CNIC Information Online with Pakdata cfHow to Check CNIC Information Online with Pakdata cf
How to Check CNIC Information Online with Pakdata cfdanishmna97
Ā 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
Ā 
Modernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using BallerinaModernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using BallerinaWSO2
Ā 

Recently uploaded (20)

Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
Ā 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
Ā 
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
TrustArc Webinar - Unified Trust Center for Privacy, Security, Compliance, an...
Ā 
JohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptx
Ā 
Simplifying Mobile A11y Presentation.pptx
Simplifying Mobile A11y Presentation.pptxSimplifying Mobile A11y Presentation.pptx
Simplifying Mobile A11y Presentation.pptx
Ā 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Ā 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
Ā 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
Ā 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Ā 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
Ā 
Introduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDMIntroduction to use of FHIR Documents in ABDM
Introduction to use of FHIR Documents in ABDM
Ā 
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
AI+A11Y 11MAY2024 HYDERBAD GAAD 2024 - HelloA11Y (11 May 2024)
Ā 
Quantum Leap in Next-Generation Computing
Quantum Leap in Next-Generation ComputingQuantum Leap in Next-Generation Computing
Quantum Leap in Next-Generation Computing
Ā 
JavaScript Usage Statistics 2024 - The Ultimate Guide
JavaScript Usage Statistics 2024 - The Ultimate GuideJavaScript Usage Statistics 2024 - The Ultimate Guide
JavaScript Usage Statistics 2024 - The Ultimate Guide
Ā 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Ā 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Ā 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
Ā 
How to Check CNIC Information Online with Pakdata cf
How to Check CNIC Information Online with Pakdata cfHow to Check CNIC Information Online with Pakdata cf
How to Check CNIC Information Online with Pakdata cf
Ā 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Ā 
Modernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using BallerinaModernizing Legacy Systems Using Ballerina
Modernizing Legacy Systems Using Ballerina
Ā 

Intro to Cypher for the SQL Developer

  • 1. Cypher for SQL Developers Mark Needham @markhneedham mark@neo4j.com
  • 2. Talk structure ā€£ Introduce data set ā€£ Modeling ā€£ Import ā€£ Data Integrity ā€£ Queries ā€£ Migration/Refactoring ā€£ Query optimisation
  • 5. Exploring transfermarkt |---------+--------------------+-----------------------------------------+--------------------+------------| | season | playerName | playerUri | playerPosition | playerAge | |---------+--------------------+-----------------------------------------+--------------------+------------| | 90/91 | Aldair | /aldair/profil/spieler/4151 | Centre Back | 24 | | 90/91 | Thomas HƤƟler | /thomas-hassler/profil/spieler/553 | Attacking Midfield | 24 | | 90/91 | Roberto Baggio | /roberto-baggio/profil/spieler/4153 | Secondary Striker | 23 | | 90/91 | Karl-Heinz Riedle | /karl-heinz-riedle/profil/spieler/13806 | Centre Forward | 24 | | 90/91 | Henrik Larsen | /henrik-larsen/profil/spieler/101330 | Attacking Midfield | 24 | | 90/91 | Gheorghe Hagi | /gheorghe-hagi/profil/spieler/7939 | Attacking Midfield | 25 | | 90/91 | Hristo Stoichkov | /hristo-stoichkov/profil/spieler/7938 | Left Wing | 24 | | 90/91 | Brian Laudrup | /brian-laudrup/profil/spieler/39667 | Centre Forward | 21 | | 90/91 | Miguel Ɓngel Nadal | /miguel-angel-nadal/profil/spieler/7676 | Centre Back | 23 | |---------+--------------------+-----------------------------------------+--------------------+------------|
  • 6. Exploring transfermarkt |-------------------+---------------------+-------------------------------------+--------------------| | sellerClubName | sellerClubNameShort | sellerClubUri | sellerClubCountry | |-------------------+---------------------+-------------------------------------+--------------------| | SL Benfica | Benfica | /benfica/startseite/verein/294 | Portugal | | 1. FC Kƶln | 1. FC Kƶln | /1-fc-koln/startseite/verein/3 | Germany | | ACF Fiorentina | Fiorentina | /fiorentina/startseite/verein/430 | Italy | | SV Werder Bremen | Werder Bremen | /werder-bremen/startseite/verein/86 | Germany | | Lyngby BK | Lyngby BK | /lyngby-bk/startseite/verein/369 | Denmark | | Steaua Bucharest | Steaua | /steaua/startseite/verein/301 | Romania | | CSKA Sofia | CSKA Sofia | /cska-sofia/startseite/verein/208 | Bulgaria | | KFC Uerdingen 05 | KFC Uerdingen | /kfc-uerdingen/startseite/verein/95 | Germany | | RCD Mallorca | RCD Mallorca | /rcd-mallorca/startseite/verein/237 | Spain | |-------------------+---------------------+-------------------------------------+--------------------|
  • 7. Exploring transfermarkt |----------------+--------------------+-------------------------------------+-------------------| | buyerClubName | buyerClubNameShort | buyerClubUri | buyerClubCountry | |----------------+--------------------+-------------------------------------+-------------------| | AS Roma | AS Roma | /as-roma/startseite/verein/12 | Italy | | Juventus FC | Juventus | /juventus/startseite/verein/506 | Italy | | Juventus FC | Juventus | /juventus/startseite/verein/506 | Italy | | SS Lazio | Lazio | /lazio/startseite/verein/398 | Italy | | AC Pisa 1909 | AC Pisa | /ac-pisa/startseite/verein/4172 | Italy | | Real Madrid | Real Madrid | /real-madrid/startseite/verein/418 | Spain | | FC Barcelona | FC Barcelona | /fc-barcelona/startseite/verein/131 | Spain | | Bayern Munich | Bayern Munich | /bayern-munich/startseite/verein/27 | Germany | | FC Barcelona | FC Barcelona | /fc-barcelona/startseite/verein/131 | Spain | |----------------+--------------------+-------------------------------------+-------------------|
  • 8. Exploring transfermarkt |--------------------------------------------------------+-------------+---------------| | transferUri | transferFee | transferRank | |--------------------------------------------------------+-------------+---------------| | /jumplist/transfers/spieler/4151/transfer_id/6993 | Ā£6.75m | 1 | | /jumplist/transfers/spieler/553/transfer_id/2405 | Ā£5.85m | 2 | | /jumplist/transfers/spieler/4153/transfer_id/84533 | Ā£5.81m | 3 | | /jumplist/transfers/spieler/13806/transfer_id/19054 | Ā£5.63m | 4 | | /jumplist/transfers/spieler/101330/transfer_id/275067 | Ā£5.03m | 5 | | /jumplist/transfers/spieler/7939/transfer_id/19343 | Ā£3.23m | 6 | | /jumplist/transfers/spieler/7938/transfer_id/11563 | Ā£2.25m | 7 | | /jumplist/transfers/spieler/39667/transfer_id/90285 | Ā£2.25m | 8 | | /jumplist/transfers/spieler/7676/transfer_id/11828 | Ā£2.10m | 9 | |--------------------------------------------------------+-------------+---------------|
  • 11. Nodes
  • 15. Relational vs Graph Records in tables Nodes "Soft" relationships computed at query time "Hard" relationships built into the data store
  • 17. Create players table CREATE TABLE players ( "id" character varying(100) NOT NULL PRIMARY KEY, "name" character varying(150) NOT NULL, "position" character varying(20) );
  • 18. Insert players 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');
  • 19. Create clubs table CREATE TABLE clubs ( "id" character varying(100) NOT NULL PRIMARY KEY, "name" character varying(50) NOT NULL, "country" character varying(50) );
  • 20. Insert clubs 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');
  • 21. Create transfers table 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) );
  • 22. Insert transfers INSERT INTO transfers VALUES('/jumplist/transfers/spieler/4151/transfer_id/6993', 'Ā£6.75m', 6750000, '90/91', 24, '/aldair/profil/spieler/4151', '/benfica/startseite/verein/294', '/as-roma/startseite/verein/12'); INSERT INTO transfers VALUES('/jumplist/transfers/spieler/553/transfer_id/2405', 'Ā£5.85m', 5850000, '90/91', 24, '/thomas-hassler/profil/spieler/553', '/1-fc- koln/startseite/verein/3', '/juventus/startseite/verein/506'); INSERT INTO transfers VALUES('/jumplist/transfers/spieler/4153/transfer_id/84533', 'Ā£5.81m', 5810000, '90/91', 23, '/roberto-baggio/profil/spieler/4153', '/fiorentina/startseite/verein/430', '/juventus/startseite/verein/506');
  • 24. LOAD CSV ā€£ Tool for importing CSV files ā€£ Intended for data sets of ~10M records ā€£ Works against live database ā€£ Use Cypher constructs to define graph
  • 25. LOAD CSV [USING PERIODIC COMMIT [1000]] LOAD CSV WITH HEADERS FROM "(file|http)://" AS row MATCH (:Label {property: row.header}) CREATE (:Label {property: row.header}) MERGE (:Label {property: row.header})
  • 26. LOAD CSV [USING PERIODIC COMMIT [1000]] LOAD CSV WITH HEADERS FROM "(file|http)://" AS row MATCH (:Label {property: row.header}) CREATE (:Label {property: row.header}) MERGE (:Label {property: row.header})
  • 27. LOAD CSV [USING PERIODIC COMMIT [1000]] LOAD CSV WITH HEADERS FROM "(file|http)://" AS row MATCH (:Label {property: row.header}) CREATE (:Label {property: row.header}) MERGE (:Label {property: row.header})
  • 28. LOAD CSV [USING PERIODIC COMMIT [1000]] LOAD CSV WITH HEADERS FROM "(file|http)://" AS row MATCH (:Label {property: row.header}) CREATE (:Label {property: row.header}) MERGE (:Label {property: row.header})
  • 29. LOAD CSV [USING PERIODIC COMMIT [1000]] LOAD CSV WITH HEADERS FROM "(file|http)://" AS row MATCH (:Label {property: row.header}) CREATE (:Label {property: row.header}) MERGE (:Label {property: row.header})
  • 30. LOAD CSV [USING PERIODIC COMMIT [1000]] LOAD CSV WITH HEADERS FROM "(file|http)://" AS row MATCH (:Label {property: row.header}) CREATE (:Label {property: row.header}) MERGE (:Label {property: row.header})
  • 31. Exploring the data LOAD CSV WITH HEADERS FROM "file:///transfers.csv" AS row RETURN COUNT(*)
  • 32. Exploring the data LOAD CSV WITH HEADERS FROM "file:///transfers.csv" AS row RETURN COUNT(*)
  • 33. Exploring the data LOAD CSV WITH HEADERS FROM "file:///transfers.csv" AS row RETURN row LIMIT 1
  • 34. Exploring the data LOAD CSV WITH HEADERS FROM "file:///transfers.csv" AS row RETURN row LIMIT 1
  • 35. Import players USING PERIODIC COMMIT LOAD CSV WITH HEADERS FROM "file:///transfers.csv" AS row CREATE (player:Player { id: row.playerUri, name: row.playerName, position: row.playerPosition })
  • 36. Import players USING PERIODIC COMMIT LOAD CSV WITH HEADERS FROM "file:///transfers.csv" AS row CREATE (player:Player { id: row.playerUri, name: row.playerName, position: row.playerPosition }) Not so fast!
  • 37. Ensure uniqueness of players CREATE CONSTRAINT ON (player:Player) ASSERT player.id IS UNIQUE
  • 38. Import players USING PERIODIC COMMIT 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]
  • 39. Import players USING PERIODIC COMMIT 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
  • 40. Import clubs CREATE CONSTRAINT ON (club:Club) ASSERT club.id IS UNIQUE
  • 41. Import selling clubs USING PERIODIC COMMIT 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
  • 42. Import buying clubs USING PERIODIC COMMIT 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
  • 43. Import transfers CREATE CONSTRAINT ON (transfer:Transfer) ASSERT transfer.id IS UNIQUE
  • 44. Import transfers 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)
  • 46. Optional Schema ā€£ Unique node property constraint
  • 47. Optional Schema ā€£ Unique node property constraint CREATE CONSTRAINT ON (club:Club) ASSERT club.id IS UNIQUE
  • 48. Optional Schema ā€£ Unique node property constraint ā€£ Node property existence constraint
  • 49. Optional Schema ā€£ Unique node property constraint ā€£ Node property existence constraint CREATE CONSTRAINT ON (club:Club) ASSERT EXISTS(club.name)
  • 50. Optional Schema ā€£ Unique node property constraint ā€£ Node property existence constraint ā€£ Relationship property existence constraint
  • 51. Optional Schema ā€£ Unique node property constraint ā€£ Node property existence constraint ā€£ Relationship property existence constraint CREATE CONSTRAINT ON ()-[player:OF_PLAYER]-() ASSERT exists(player.age)
  • 54. SELECT * FROM players WHERE players.name = 'Cristiano Ronaldo'
  • 55. SELECT * FROM players WHERE players.name = 'Cristiano Ronaldo' MATCH (player:Player { name: "Cristiano Ronaldo" }) RETURN player
  • 56. SELECT * FROM players WHERE players.name = 'Cristiano Ronaldo' MATCH (player:Player { name: "Cristiano Ronaldo" }) RETURN player
  • 57. SELECT * FROM players WHERE players.name = 'Cristiano Ronaldo' MATCH (player:Player { name: "Cristiano Ronaldo" }) RETURN player
  • 58.
  • 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'
  • 61. 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
  • 62. 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
  • 63.
  • 64. How does Neo4j use indexes? Indexes are only used to find the starting point for queries. Use index scans to look up rows in tables and join them with rows from other tables Use indexes to find the starting points for a query. Relational Graph
  • 65. How does Neo4j use indexes?
  • 67. Player nationality |------------------------------------------+--------------------+--------------------| | playerUri | playerName | playerNationality | |------------------------------------------+--------------------+--------------------| | /aldair/profil/spieler/4151 | Aldair | Brazil | | /thomas-hassler/profil/spieler/553 | Thomas HƤƟler | Germany | | /roberto-baggio/profil/spieler/4153 | Roberto Baggio | Italy | | /karl-heinz-riedle/profil/spieler/13806 | Karl-Heinz Riedle | Germany | | /henrik-larsen/profil/spieler/101330 | Henrik Larsen | Denmark | | /gheorghe-hagi/profil/spieler/7939 | Gheorghe Hagi | Romania | | /hristo-stoichkov/profil/spieler/7938 | Hristo Stoichkov | Bulgaria | | /brian-laudrup/profil/spieler/39667 | Brian Laudrup | Denmark | | /miguel-angel-nadal/profil/spieler/7676 | Miguel Ɓngel Nadal | Spain | |------------------------------------------+--------------------+--------------------|
  • 70. Add column to players table ALTER TABLE players ADD COLUMN nationality varying(30);
  • 71. Update players table 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';
  • 74. Add property to player nodes USING PERIODIC COMMIT LOAD CSV WITH HEADERS FROM "file:///transfers.csv" AS row MATCH (player:Player {id: row.playerUri}) SET player.nationality = row.playerNationality
  • 75. Find transfers of English players
  • 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
  • 77. 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
  • 78. 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
  • 79.
  • 80. Countries and confederations |----------------------+----------------| | 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 | |-----------+-----------+-------------------------------------------------|
  • 83. Create confederations table 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 );
  • 84. Populate confederations 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');
  • 85. Create countries table 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) );
  • 86. Populate countries 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');
  • 87. Add column to clubs table ALTER TABLE clubs ADD COLUMN country_id character varying(3) REFERENCES countries(code);
  • 88. Update clubs 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;
  • 89. Update clubs # 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. Remove country ALTER TABLE clubs DROP COLUMN country;
  • 91. Add column to players table ALTER TABLE players ADD COLUMN country_id character varying(3) REFERENCES countries(code);
  • 92. Update players 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;
  • 93. Update players # 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)
  • 94. Remove nationality ALTER TABLE players DROP COLUMN nationality;
  • 97. Import confederations 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
  • 98. Import countries LOAD CSV WITH HEADERS FROM "file:///countries.csv" AS row MERGE (country:Country {id: row.countryCode}) ON CREATE SET country.name = row.country WITH country, row MATCH (conf:Confederation {id: row.confederation }) MERGE (country)-[:PART_OF]->(conf)
  • 99. Refactor clubs MATCH (club:Club) MATCH (country:Country {name: club.country}) MERGE (club)-[:PART_OF]->(country) REMOVE club.country
  • 100. Refactor players MATCH (player:Player) MATCH (country:Country {name: player.nationality}) MERGE (player)-[:PLAYS_FOR]->(country) REMOVE player.nationality
  • 101. Recap: Find transfers of English players
  • 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 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
  • 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)-[: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. 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)-[: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
  • 105. 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)-[: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
  • 107. 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
  • 108. 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
  • 109.
  • 110. Whatā€™s in my database?
  • 111. Tables # 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)
  • 113. CALL db.labels() +=============+ |label | +=============+ |Player | +-------------+ |Club | +-------------+ |Transfer | +-------------+ |Loan | +-------------+ |Confederation| +-------------+ |Country | +-------------+ Node labels
  • 114. Table schema # d+ countries Table "public.countries" Column | Type | Modifiers | Storage | Stats target | Description ------------+-----------------------+-----------+----------+--------------+------------- code | character varying(3) | not null | extended | | name | character varying(50) | not null | extended | | federation | character varying(10) | not null | extended | | Indexes: "pk_countries" PRIMARY KEY, btree (code) Foreign-key constraints: "countries_federation_fkey" FOREIGN KEY (federation) REFERENCES confederations(id) Referenced by: TABLE "players" CONSTRAINT "playersfk" FOREIGN KEY (country_id) REFERENCES countries(code) MATCH FULL
  • 115. :schema Indexes ON :Club(name) ONLINE ON :Club(id) ONLINE (for uniqueness constraint) ON :Player(name) ONLINE ON :Player(id) ONLINE (for uniqueness constraint) Constraints ON (player:Player) ASSERT player.id IS UNIQUE ON (club:Club) ASSERT exists(club.name) ON (club:Club) ASSERT club.id IS UNIQUE ON ()-[of_player:OF_PLAYER]-() ASSERT exists(of_player.age) Graph schema
  • 116. MATCH (country:Country) RETURN keys(country), COUNT(*) AS times +-----------------------+ | keys(country) | times | +-----------------------+ | ["id","name"] | 198 | +-----------------------+ Graph schema
  • 117. Graph schema MATCH (club:Club) RETURN keys(club), COUNT(*) AS times +---------------------------------+ | keys(club) | times | +---------------------------------+ | ["id","name"] | 806 | | ["name","country","id"] | 1 | +---------------------------------+
  • 120. Meta graph MATCH (a)-[r]->(b) WITH head(labels(a)) AS l, head(labels(b)) AS l2, type(r) AS rel_type, count(*) as count CALL apoc.create.vNode([l],{name:l}) yield node as a CALL apoc.create.vNode([l2],{name:l2}) yield node as b CALL apoc.create.vRelationship(a,rel_type,{name:rel_type, count:count},b) YIELD rel RETURN *;
  • 122. Clubs without country # 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)
  • 123. Clubs without country 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}| +---------------------------------------------------------------------+
  • 124. Deleting data - SQL # 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.
  • 125. MATCH (country:Country) DELETE country org.neo4j.kernel.api.exceptions.TransactionFailureException: Node record Node[11306,used=false,rel=24095,prop=-1,labels=Inline(0x0: []),light] still has relationships Deleting data - Cypher
  • 126. MATCH (country:Country) DETACH DELETE country Deleted 198 nodes, deleted 5071 relationships, statement executed in 498 ms. Deleting data - Cypher
  • 128. Optimising queries ā€£ Use EXPLAIN/PROFILE to see what your queries are doing under the covers ā€£ Index the starting points of queries ā€£ Reduce work in progress of intermediate parts of the query where possible ā€£ Look at the warnings in the Neo4j browser - they are often helpful!
  • 129. Optimising queries - useful links ā€£ Tuning Your Cypher https://www.youtube.com/watch?v=tYtyoYcd_e8 ā€£ Neo4j 2.2 Query Tuning http://neo4j.com/blog/neo4j-2-2-query-tuning/ ā€£ Ask for help on Stack Overflow/Neo4j Slack http://neo4j-users-slack-invite.herokuapp.com
  • 131. ā€£ New in Neo4j 3.0.0! Procedures
  • 132. ā€£ New in Neo4j 3.0.0! ā€£ Weā€™ve already seen an example! CALL db.labels() ā€£ Michael Hunger has created a set of procedures (APOC) at: https://github.com/jexp/neo4j-apoc-procedures Procedures
  • 133. WITH "https://api.github.com/search/repositories?q=neo4j" AS githubUri CALL apoc.load.json(githubUri) YIELD value AS document UNWIND document.items AS item RETURN item.full_name, item.watchers_count, item.forks ORDER BY item.forks DESC Querying github
  • 134. WITH "https://api.github.com/search/repositories?q=neo4j" AS githubUri CALL apoc.load.json(githubUri) YIELD value AS document UNWIND document.items AS item RETURN item.full_name, item.watchers_count, item.forks ORDER BY item.forks DESC Querying github
  • 135. +------------------------------------------------------------------------+ | item.full_name | item.watchers_count | item.forks | +------------------------------------------------------------------------+ | "neo4j/neo4j" | 2472 | 872 | | "spring-projects/spring-data-neo4j" | 403 | 476 | | "neo4j-contrib/developer-resources" | 106 | 295 | | "neo4jrb/neo4j" | 1014 | 190 | | "jadell/neo4jphp" | 507 | 140 | | "thingdom/node-neo4j" | 780 | 127 | | "aseemk/node-neo4j-template" | 176 | 91 | | "jimwebber/neo4j-tutorial" | 268 | 87 | | "rickardoberg/neo4j-jdbc" | 33 | 68 | | "FaKod/neo4j-scala" | 194 | 64 | +------------------------------------------------------------------------+ Querying github