Training GDS Introduction Graph Databases - tomgeudens/practical-neo4j GitHub Wiki
Context: Cut-and-paste commands for the Graph Data Science - Introduction to Graph Databases session.
Prerequisite: This document will assume you have a Neo4j instance running and are connected to it with the Neo4j Browser. You also need to have the Game of Thrones database loaded.
Game of Thrones Database Model
001
// make sure you're in the correct database
:use gameofthrones
002
// visualize the model
CALL db.schema.visualization();
Plain MATCH
003
// Find and return all nodes in the database
MATCH (x)
RETURN x;
Label MATCH
004
// Find and return all House nodes in the database
MATCH (y:House)
RETURN y;
005
// Find and return all Person nodes in the database that also have the King and the Dead label
MATCH (z:Person:King:Dead)
RETURN z;
Relationships
006
// Which houses where present in which battles?
MATCH (x:House)-[]->(y:Battle)
RETURN x.name, y.name;
// Which houses where present in which battles (condensed syntax)?
MATCH (h:House)-->(b:Battle)
RETURN h.name, b.name;
007
// Which houses attacked in which battles?
MATCH (x:House)-[y:ATTACKER]->(z:Battle)
RETURN x,y,z
LIMIT 30;
008
// Which houses attacked or defended in which battles?
MATCH (x:House)-[y:ATTACKER|DEFENDER]->(z:Battle)
RETURN x,y,z
LIMIT 30;
Awesome Procedures On Cypher
009
// Generate a UUID and return it and the versions of APOC and GDS
RETURN apoc.create.uuid() as uuid, apoc.version() as apocversion, gds.version() as gdsversion;
010
// Find out about the signature of a procedure
CALL apoc.help("help") YIELD signature
RETURN signature;
011
// Show which procedures can bulk load data into the database
CALL apoc.help("load") YIELD type, name, text, signature, core
RETURN type, name, text, signature, core;
WHERE
012
// So these are braces ...
MATCH (x:House {name:"Darry"})-[y:DEFENDER]->(z:Battle)
RETURN x,y,z;
013
// And they are the equivalent of checking for equality
MATCH (x:House)-[y:DEFENDER]->(z:Battle)
WHERE x.name = "Darry"
RETURN x,y,z;
014
// In the WHERE clause you have the full range of options
MATCH (x:Person)-[:BELONGS_TO]->(y:House)
WHERE x.death_year >= 300 AND x.death_year <= 1200
RETURN x.name, y.name;
015
// And that includes a range query
MATCH (x:Person)-[:BELONGS_TO]->(y:House)
WHERE 300 <= x.death_year <= 1200
RETURN x.name, y.name;
Aggregation
016
// How many persons does each house have?
MATCH (x:Person)-[:BELONGS_TO]->(y:House)
RETURN y.name as Housename, count(*) as Household;
017
// Which commanders didn't learn the first time?
MATCH (x:Person)-[:ATTACKER_COMMANDER]->(y:Battle)<-[:DEFENDER_COMMANDER]-(z:Person)
RETURN x.name AS attacker, z.name as defender, count(y) AS commonBattles, collect(y.name) AS battlenames
ORDER BY commonBattles DESC LIMIT 5;
Deduplication
018
// Just Jon, right?
MATCH (x:Person {name: "Jon Snow"})-[:INTERACTS]->()
RETURN x;
019
// Counting Jon
MATCH (x:Person {name: "Jon Snow"})-[:INTERACTS]->()
RETURN count(x);
020
// I am the only Jon
MATCH (x:Person {name: "Jon Snow"})-[:INTERACTS]->()
RETURN DISTINCT x;
// I am the only Jon
MATCH (x:Person {name: "Jon Snow"})-[:INTERACTS]->()
RETURN count(DISTINCT x);
WITH
021
// Who was attacking commander in exactly two battles?
MATCH (x:Person)-[:ATTACKER_COMMANDER]->(y:Battle)
WITH x.name as name, count(*) AS numBattles, collect(y.name) as battles
WHERE numBattles = 2
RETURN name, numBattles, battles;
UNWIND
022
// How many results come out?
WITH range(1,5) as acollection
UNWIND acollection as arow
WITH arow, acollection, apoc.coll.shuffle(acollection) as ashuffle
UNWIND ashuffle as anotherrow
RETURN arow, anotherrow, acollection,ashuffle;
023
// Aggressive lot, these
MATCH (x:House)-[:ATTACKER]->()
WITH collect(DISTINCT x) AS attackers
MATCH (y:House)-[:DEFENDER]->()
WITH attackers, collect(DISTINCT y) AS defenders
UNWIND apoc.coll.removeAll(attackers,defenders) AS houses
RETURN houses.name as Names;