Slides can be found here
Neo4j is an open-source NoSQL graph database implemented in Java and Scala. It implements the Property Graph Model efficiently down to the storage level, and provides full database characteristics including ACID transaction compliance, cluster support and runtime failover.
- Java 8
- Neo4J 3.2+
By default Neo4j requires authentication and requires you to login with neo4j/neo4j at the first connection and set a new password.
- Run
brew install neo4j
. This will updatebrew
and install Neo4J (version 3.2 or higher). - Run
neo4j version
to verify the version installed. - Set the password before starting up the database for the first time:
neo4j-admin set-initial-password <password>
- Change the local repo path and password in the following command and run it:
docker run \ --publish=7474:7474 --publish=7687:7687 \ --volume=$HOME/neo4j/data:/data \ --volume=$HOME/neo4j/logs:/logs \ --volume=/<path_to__ws_repo>:/var/lib/neo4j/import \ --env NEO4J_AUTH=neo4j/<password> \ --detach --name neo4j-101-ws \ neo4j:latest
Cypher is a declarative graph query language that allows for expressive and efficient querying and updating of the graph store.
- Brew:
neo4j start
cypher-shell --username neo4j
- Docker:
docker exec --interactive --tty neo4j-101-ws bin/cypher-shell --username neo4j
:exit
:help
:history
()
(movie)
(:Movie)
(movie:Movie)
(movie:Movie { title: "The Lord of the Rings: The Fellowship of the Ring" })
(movie:Movie { title: "The Lord of the Rings: The Fellowship of the Ring", released: 2001 })
-->
-[role]->
-[:ACTED_IN]->
-[role:ACTED_IN]->
-[role:ACTED_IN { roles: ["Aragorn"] }]->
(actor:Actor { name: "Viggo Mortensen" })
-[role:ACTED_IN { roles: ["Aragorn"] }]->
(movie:Movie { title: "The Lord of the Rings: The Fellowship of the Ring" })
acted_in = (:Person)-[:ACTED_IN]->(:Movie)
CREATE (actor:Actor { name:"Viggo Mortensen", born:1958 });
MATCH (actor:Actor { name:"Viggo Mortensen"})
CREATE (movie:Movie { title: "The Lord of the Rings: The Fellowship of the Ring", released: 2001 })
CREATE (actor)-[role:ACTED_IN { roles: ["Aragorn"] }]->(movie);
MERGE (movie:Movie { title:"Alatriste" })
ON CREATE SET movie.released = 2006;
MATCH (movie:Movie { title:"Alatriste" })
MATCH (actor:Actor { name:"Viggo Mortensen" })
MERGE (actor)-[role:ACTED_IN]->(movie)
ON CREATE SET role.roles = ["Captain Diego Alatriste"];
MATCH (movie { title: "Alatriste" })
SET movie.country = "Spain";
MATCH (movie { title: "Alatriste" })
REMOVE movie.country;
MATCH (n)
DELETE n;
MATCH ()-[r]-()
DELETE (r);
- Create a single node with no labels and no properties
- Create multiple nodes in a single
CREATE
statement - Create a node with multiple labels
- Remove a label from a node
- Create a node and return it in the same statement
- Create a full path in a single
CREATE
statement - Update an existing node and set a property if a match is found
- Copy properties between two nodes
- Delete a node with existing relationships
- Delete an specific type of relationship
- Delete a node with a specific label
To test the following queries you can execute the following:
MATCH (n) DETACH DELETE n;
CREATE (viggo:Actor { name:"Viggo Mortensen", born:1958 }),
(lotr:Movie { title: "The Lord of the Rings: The Fellowship of the Ring", released: 2001 }),
(alatriste:Movie { title:"Alatriste", country: "Spain", released: 2006 }),
(viggo)-[:ACTED_IN { roles: ["Aragorn"] }]->(lotr),
(viggo)-[:ACTED_IN { roles: ["Captain Diego Alatriste"] }]->(alatriste);
MATCH (n)
RETURN n;
MATCH (:Actor { name: 'Viggo Mortensen' })--(movie:Movie)
RETURN movie.title AS title;
MATCH (:Actor { name: 'Viggo Mortensen' })-[r]->(movie)
RETURN DISTINCT type(r);
MATCH (alatriste:Movie { title: 'Alatriste' })<-[:ACTED_IN]-(actor)
RETURN actor.name;
MATCH p =(viggo { name: 'Viggo Mortensen' })-->()
RETURN p;
MATCH p =(viggo { name: 'Viggo Mortensen' })-->()
RETURN *;
MATCH (actor:Actor)
WHERE actor.name CONTAINS 'Viggo'
RETURN actor.born > 1970, "I'm a literal", (actor)-->();
MATCH (n)
WHERE exists(n.title)
RETURN n;
MATCH (actor:Actor)-->(movie)
WITH actor, count(*) AS appearances
WHERE appearances > 1
RETURN actor.name;
MATCH (n)
WITH n
ORDER BY n.title DESC LIMIT 3
WHERE exists(n.title)
RETURN collect(n.title);
Given the following CSV files:
persons.csv
id,name
1,Charlie Sheen
2,Oliver Stone
3,Michael Douglas
4,Martin Sheen
5,Morgan Freeman
movies.csv
id,title,country,year
1,Wall Street,USA,1987
2,The American President,USA,1995
3,The Shawshank Redemption,USA,1994
roles.csv
personId,movieId,role
1,1,Bud Fox
4,1,Carl Fox
3,1,Gordon Gekko
4,2,A.J. MacInerney
3,2,President Andrew Shepherd
5,3,Ellis Boyd 'Red' Redding
we can import its data to Neo4J as follows:
CREATE CONSTRAINT ON (person:Person) ASSERT person.id IS UNIQUE;
LOAD CSV WITH HEADERS FROM "file:///persons.csv" AS csvLine
CREATE (p:Person { id: toInteger(csvLine.id), name: csvLine.name });
CREATE CONSTRAINT ON (movie:Movie) ASSERT movie.id IS UNIQUE;
CREATE INDEX ON :Country(name);
LOAD CSV WITH HEADERS FROM "file:///movies.csv" AS csvLine
MERGE (country:Country { name: csvLine.country })
CREATE (movie:Movie { id: toInteger(csvLine.id), title: csvLine.title, year:toInteger(csvLine.year)})
CREATE (movie)-[:MADE_IN]->(country);
USING PERIODIC COMMIT 500
LOAD CSV WITH HEADERS FROM "file:///roles.csv" AS csvLine
MATCH (person:Person { id: toInteger(csvLine.personId)}),(movie:Movie { id: toInteger(csvLine.movieId)})
CREATE (person)-[:PLAYED { role: csvLine.role }]->(movie);
DROP CONSTRAINT ON (person:Person) ASSERT person.id IS UNIQUE;
DROP CONSTRAINT ON (movie:Movie) ASSERT movie.id IS UNIQUE;
MATCH (n)
WHERE n:Person OR n:Movie
REMOVE n.id;
For security reasons, all file://
URLs are always relative to the standard import directory ($NEO4J_HOME/import
).
Given the following ASCII art:
(:NationalTeam {name})<-[:REPRESENTS]-(:Player {name})-[:PLAYS_FOR]->(:Club {name})
-
Load the CSV files found in the
exercise02
folder to create this graph.$NEO4J_HOME
is/usr/local/Cellar/neo4j/<version>/libexec
if you installed Neo4J using Brew. Copy the files into the import directory:cp -R exercise02 /usr/local/Cellar/neo4j/<version>/libexec/import
For Docker, this data is already available in the right folder if you followed the instructions.
-
Once the data is loaded, answer the following questions:
- Which are the top 10 clubs with the most players being called by their national teams? Display the club name and the number of international players.
- Using the top 1 club from the previous question, who are the players and where do they come from? Display the country name, the number of players and a list with its names.
- In which clubs are playing the members of a given national team? Display the club name, the number of players and a list with its names.
- What country needs to pick from less clubs to build their national team? Display the country name and the number of distinct clubs.
NOTE: You can connect to http://localhost:7474 to use the Neo4J Browser to resolve this exercise.
Also, you can use the Neo4J Cypher Refcard to find more information about Cypher.