Training Lightning Basics - tomgeudens/practical-neo4j GitHub Wiki
Context: Cut-and-paste commands for the Lightning Basics training.
Prerequisite: You are attending a Neo4j Lightning Basics training.
Twenty Minutes
From bank to Panama
MATCH sg=(:Bank {name: "KBC Bank NV"})-[*]-(:Country {name: "Panama"})
RETURN sg;
Shortest way from bank to Panama
MATCH sg=shortestPath( (:Bank {name: "KBC Bank NV"})-[*]-(:Country {name: "Panama"}) )
RETURN sg;
The usual suspect
MATCH sg=(:Bank {name: "KBC Bank NV"})-[*]-(:Person {name: "Vladimir Putin"})-[*]-(:Country {name: "Panama"})
RETURN sg;
Any person
MATCH (:Bank {name: "KBC Bank NV"})-[*]-(x:Person)-[*]-(:Country {name: "Panama"})
RETURN DISTINCT x.name as suspect;
Flexible model in action
MATCH (p:Person {name: "Tom Geudens"})
SET p:Fraudster;
Fraudsters only
MATCH (f:Fraudster)
RETURN f;
Cypher ASCII Art
The mysterious Mr White
MATCH (p:Person {name: "Tom Hanks"}) RETURN p
MATCH ()-[ai:ACTED_IN {roles: ["Mr. White"]}]-() RETURN ai
MATCH (x)-[ai:ACTED_IN {roles: ["Mr. White"]}]-(y) RETURN x.name, x.title, ai.roles, y.name, y.title
Lock & Load
Inspection - Expected number of Movie nodes
LOAD CSV FROM 'http://data.neo4j.com/intro/movies/movies.csv'
AS row
RETURN count(*);
Inspection - Expected number of Person nodes
LOAD CSV FROM 'http://data.neo4j.com/intro/movies/people.csv'
AS row
RETURN count(*);
Inspection - Expected number of DIRECTED relationships
LOAD CSV FROM 'http://data.neo4j.com/intro/movies/directors.csv' AS row
RETURN count(*);
Inspection - Expected number of ACTED_IN relationships
LOAD CSV FROM 'http://data.neo4j.com/intro/movies/actors.csv' AS row
RETURN count(*);
Inspection - Visually
LOAD CSV FROM 'http://data.neo4j.com/intro/movies/movies.csv' AS row
RETURN * LIMIT 5;
Inspection - Visually ... WITH HEADERS
LOAD CSV WITH HEADERS FROM 'http://data.neo4j.com/intro/movies/movies.csv' AS row
RETURN row, keys(row) LIMIT 5;
Inspection - Casting
LOAD CSV WITH HEADERS FROM 'http://data.neo4j.com/intro/movies/movies.csv' AS row
RETURN row.title as title, toInteger(row.released) as released, row.tagline as tagline
ORDER BY released DESC LIMIT 10;
Bulk loading done wrong
LOAD CSV WITH HEADERS FROM 'http://data.neo4j.com/intro/movies/movies.csv' AS row
CREATE (m:Movie {title: row.title, released: toInteger(row.released), tagline: row.tagline})
RETURN m;
Cleanup
CALL apoc.periodic.commit(
"MATCH ()-[r]->() WITH r LIMIT $limit DELETE r RETURN count(*)",
{limit:2000}
);
CALL apoc.periodic.commit(
"MATCH (n) WITH n LIMIT $limit DELETE n RETURN count(*)",
{limit:2000}
);
Schema first
CREATE CONSTRAINT uc_Movie_title ON (m:Movie) ASSERT m.title IS UNIQUE;
CREATE CONSTRAINT uc_Person_name ON (p:Person) ASSERT p.name IS UNIQUE;
Movie nodes
LOAD CSV WITH HEADERS FROM 'http://data.neo4j.com/intro/movies/movies.csv' AS row
CREATE (:Movie {title: row.title, released: toInteger(row.released), tagline: row.tagline});
Check Movie nodes
MATCH (:Movie) RETURN count(*);
Person nodes
LOAD CSV WITH HEADERS FROM 'http://data.neo4j.com/intro/movies/people.csv' AS row
CREATE (:Person {name: row.name, born: toInteger(row.born)});
Check Person nodes
MATCH (:Person) RETURN count(*);
DIRECTED relationships
LOAD CSV WITH HEADERS FROM 'http://data.neo4j.com/intro/movies/directors.csv' AS row
MATCH (p:Person {name: row.person })
MATCH (m:Movie {title: row.movie})
MERGE (p)-[:DIRECTED]->(m);
Check DIRECTED relationships
MATCH ()-[:DIRECTED]->() RETURN count(*);
ACTED_IN relationships
LOAD CSV WITH HEADERS FROM 'http://data.neo4j.com/intro/movies/actors.csv'
AS row
MATCH (p:Person {name: row.person })
MATCH (m:Movie {title: row.movie})
MERGE (p)-[actedIn:ACTED_IN]->(m)
ON CREATE SET actedIn.roles = split(row.roles,';');
Check ACTED_IN relationships
MATCH ()-[:ACTED_IN]->() RETURN count(*);
Something weird going on here ...
MATCH(p:Person {name: "Tom Hanks"})-[ai:ACTED_IN]-(m:Movie) RETURN p,ai,m;
Something's Gotta Give
MATCH (m:Movie) WHERE m.title STARTS WITH "Something"
RETURN m, keys(m);
Cypher Strikes Back
Finding Tom
MATCH (p:Person {name: "Tom Hanks"})
RETURN p;
Finding Tom II
MATCH (p:Person)
WHERE p.name = "Tom Hanks"
RETURN p;
Analyzing finding Tom
PROFILE MATCH (p:Person {name: "Tom Hanks"})
RETURN p;
Analyzing finding Tom II
PROFILE MATCH (p:Person)
WHERE p.name = "Tom Hanks"
RETURN p;
Analyzing without finding Tom
EXPLAIN MATCH (p:Person {name: "Tom Hanks"})
RETURN p;
Did Tom act with Tom ?
MATCH (p1:Person)-[a1:ACTED_IN]->(m:Movie)<-[a2:ACTED_IN]-(p2:Person)
WHERE p1.name = "Tom Hanks"
AND p2.name = "Tom Cruise"
RETURN p1.name, a1.roles, p2.name, a2.roles, m.title;
Did Tom act with Kevin ?
MATCH (p1:Person)-[a1:ACTED_IN]->(m:Movie)<-[a2:ACTED_IN]-(p2:Person)
WHERE p1.name = "Tom Hanks"
AND p2.name = "Kevin Bacon"
RETURN p1.name, a1.roles, p2.name, a2.roles, m.title;
Create myself as a trainer ...
CREATE (:Trainer {name: "Tom Geudens"});
Cleanup
MATCH (t:Trainer) DELETE t;
Add schema
CREATE CONSTRAINT ON (t:Trainer) ASSERT t.name IS UNIQUE;
CREATE CONSTRAINT ON (t:Training) ASSERT t.title IS UNIQUE;
Create myself as the trainer and create the training
CREATE (:Trainer {name: "Tom Geudens"})
CREATE (:Training {title: "Basics"});
Create the relationship
MATCH (t:Training {title: "Basics"})
MATCH (tr:Trainer {name: "Tom Geudens"})
MERGE (tr)-[te:TEACHES {location: "Online", when: date("2021-06-04")}]->(t)
RETURN tr,te,t;
Just an update?
MATCH (tr:Trainer {name: "Tom Geudens"})-[t:TEACHES]->(f:Training {title: "Basics"})
SET tr.age = 48, t.at = time("10:00:00"), f.duration = duration("PT2H")
RETURN tr, t, f;
Return with a recommendation
Who should play with Tom
MATCH (tom:Person {name: "Tom Hanks"})-[:ACTED_IN]->(m1:Movie)<-[:ACTED_IN]-(coActors:Person)-[:ACTED_IN]->(m2:Movie)<-[:ACTED_IN]-(cocoActors:Person)
WHERE NOT (tom)-[:ACTED_IN]->()<-[:ACTED_IN]-(cocoActors)
AND tom <> cocoActors
RETURN cocoActors.name AS Recommended, count(*) AS Strength ORDER BY Strength DESC;
But it's wrong, isn't it?
MATCH (tom:Person {name: "Tom Hanks"})-[:ACTED_IN]->(m1:Movie)<-[:ACTED_IN]-(coActors:Person)-[:ACTED_IN]->(m2:Movie)<-[:ACTED_IN]-(cocoActors:Person)
WHERE NOT (tom)-[:ACTED_IN]->()<-[:ACTED_IN]-(cocoActors)
AND tom <> cocoActors
RETURN cocoActors.name AS Recommended, collect(coActors.name) as thisiswrong, count(*) AS Strength ORDER BY Strength DESC;
Much better
MATCH (tom:Person {name: "Tom Hanks"})-[:ACTED_IN]->(m1:Movie)<-[:ACTED_IN]-(coActors:Person)-[:ACTED_IN]->(m2:Movie)<-[:ACTED_IN]-(cocoActors:Person)
WHERE NOT (tom)-[:ACTED_IN]->()<-[:ACTED_IN]-(cocoActors)
AND tom <> cocoActors
RETURN cocoActors.name AS Recommended, collect(DISTINCT coActors.name), count(DISTINCT coActors.name) AS Strength ORDER BY Strength DESC;