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;