Graph Databases: neo4j

Property Graphs

Key features of Property Graph Model

Once neo4j server has started, you can use http://localhost:7474/browser/ to browse the database or you can use cypher-shell to interact.

Create User

Mac-mini:neo4j raj$ cypher-shell
username: neo4j
password: ****
Connected to Neo4j 4.1.0 at neo4j://localhost:7687 as user neo4j.
Type :help for a list of available commands or :exit to exit the shell.
Note that Cypher queries must end with a semicolon.

neo4j@neo4j> show users;
+------------------------------------------------------+
| user    | roles | passwordChangeRequired | suspended |
+------------------------------------------------------+
| "neo4j" | NULL  | FALSE                  | NULL      |
+------------------------------------------------------+

1 row available after 338 ms, consumed after another 9 ms

neo4j@neo4j> create user raj set password 'r123';
0 rows available after 368 ms, consumed after another 0 ms

neo4j@neo4j> show users;
+------------------------------------------------------+
| user    | roles | passwordChangeRequired | suspended |
+------------------------------------------------------+
| "neo4j" | NULL  | FALSE                  | NULL      |
| "raj"   | NULL  | TRUE                   | NULL      |
+------------------------------------------------------+

2 rows available after 11 ms, consumed after another 4 ms

neo4j@neo4j> drop user raj;
0 rows available after 333 ms, consumed after another 0 ms

neo4j@neo4j> show users;
+------------------------------------------------------+
| user    | roles | passwordChangeRequired | suspended |
+------------------------------------------------------+
| "neo4j" | NULL  | FALSE                  | NULL      |
+------------------------------------------------------+

1 row available after 12 ms, consumed after another 3 ms

neo4j@neo4j> create user raj set password 'r123' change not required;
0 rows available after 82 ms, consumed after another 0 ms

neo4j@neo4j> show users;
+------------------------------------------------------+
| user    | roles | passwordChangeRequired | suspended |
+------------------------------------------------------+
| "neo4j" | NULL  | FALSE                  | NULL      |
| "raj"   | NULL  | FALSE                  | NULL      |
+------------------------------------------------------+

2 rows available after 9 ms, consumed after another 5 ms

neo4j@neo4j> :exit
Bye!

Cypher Query Language (CQL)

https://neo4j.com/docs/cypher-manual/current/

Create

CREATE (john:Person {name: 'John'})
CREATE (joe:Person {name: 'Joe'})
CREATE (steve:Person {name: 'Steve'})
CREATE (sara:Person {name: 'Sara'})
CREATE (maria:Person {name: 'Maria'})
CREATE (john)-[:FRIEND]->(joe)-[:FRIEND]->(steve)
CREATE (john)-[:FRIEND]->(sara)-[:FRIEND]->(maria)

Query

MATCH (john {name: 'John'})-[:FRIEND]->(f)
RETURN john.name, f.name

returns

╒═══════════╤════════╕
│"john.name"│"f.name"│
╞═══════════╪════════╡
│"John"     │"Sara"  │
├───────────┼────────┤
│"John"     │"Joe"   │
└───────────┴────────┘
MATCH (john {name: 'John'})-[:FRIEND]->()-[:FRIEND]->(fof)
RETURN john.name, fof.name

returns

╒═══════════╤══════════╕
│"john.name"│"fof.name"│
╞═══════════╪══════════╡
│"John"     │"Maria"   │
├───────────┼──────────┤
│"John"     │"Steve"   │
└───────────┴──────────┘

Movie DB Queries

Find all Movies.

Mac-mini:movies raj$ more c1.cql 
// Find all Movies.
MATCH (n:Movie) 
RETURN n;

Mac-mini:movies raj$ cat c1.cql | cypher-shell -u raj -p r123
n
(:Movie {name: "Star Wars", country: "USA", id: "m1", year: 1978})
(:Movie {name: "Gandhi", country: "UK", id: "m2", year: 1982})
(:Movie {name: "Ran", country: "Japan", id: "m3", year: 1972})
(:Movie {name: "Sting", country: "USA", id: "m4", year: 1976})
(:Movie {name: "Wizard of OZ", country: "USA", id: "m5", year: 1948})
(:Movie {name: "Money Ball", country: "USA", id: "m6", year: 2009})

Find all Movies that were made after 1960.

Mac-mini:movies raj$ more c2.cql 
// Find all Movies that were made after 1960.
MATCH (n:Movie) 
WHERE n.year > 1960
RETURN n.name,n.year;

Mac-mini:movies raj$ cat c2.cql | cypher-shell -u raj -p r123
n.name, n.year
"Star Wars", 1978
"Gandhi", 1982
"Ran", 1972
"Sting", 1976
"Money Ball", 2009

Find all Theaters in Atlanta.

Mac-mini:movies raj$ more c3.cql 
// Find all Theaters in Atlanta.
MATCH (n:Theater {city:"Atlanta"})
RETURN n.name as TNAME;

Mac-mini:movies raj$ cat c3.cql | cypher-shell -u raj -p r123
TNAME
"Odeon"
"Multiplex II"

Find names of screens in theater named Odeon

Mac-mini:movies raj$ more c4.cql 
// Find names of screens in theater named "Odeon"
MATCH (t:Theater)-[:has_screen]->(s:Screen)
WHERE t.name = "Odeon"
RETURN s.name;

Mac-mini:movies raj$ cat c4.cql | cypher-shell -u raj -p r123
s.name
"West I"
"North III"
"North II"
"North I"

Find screenings of Gandhi in Doraville

Mac-mini:movies raj$ more c5.cql 
// Find screenings of "Gandhi" in "Doraville"
MATCH (t:Theater)-[:has_screen]->(s:Screen)-[p:plays_movie]->(m:Movie) 
WHERE t.city = "Doraville" and m.name = "Gandhi"
RETURN t.name, s.name, p.date, p.time, p.price;

Mac-mini:movies raj$ cat c5.cql | cypher-shell -u raj -p r123
t.name, s.name, p.date, p.time, p.price
"Multiplex I", "Magnolia II", "11/16/2011", "9pm", 8
"Multiplex I", "Magnolia II", "11/15/2011", "6pm", 8
"Multiplex I", "Magnolia II", "11/15/2011", "3pm", 5
"Multiplex I", "Magnolia II", "11/15/2011", "12pm", 5
"Multiplex I", "Magnolia I", "11/15/2011", "9pm", 8

The above query could be written as

// Find screenings of "Gandhi" in "Doraville"
MATCH (t:Theater)-->(s:Screen)-[p:plays_movie]->(m:Movie) 
WHERE t.city = "Doraville" and m.name = "Gandhi"
RETURN t.name, s.name, p.date, p.time, p.price;

Notice the use of --> between two nodes, indicating a path via one edge

Find names of theaters and count of screens for each

Mac-mini:movies raj$ more c7.cql 
// Find names of theaters and count of screens for each
MATCH (t:Theater)-[s:has_screen]->(:Screen)
RETURN t.name, count(s);

Mac-mini:movies raj$ cat c7.cql | cypher-shell -u raj -p r123
t.name, count(s)
"Odeon", 4
"Multiplex I", 3
"Multiplex II", 2

Delete

Delete entire database (all nodes/edges!)

drinks@neo4j> match (n) detach delete n;
0 rows available after 37 ms, consumed after another 0 ms
Deleted 155 nodes, Deleted 143 relationships

Update

Using Set clause, you can add new properties to an existing Node or Relationship, and also add or update existing Properties values. The following are possible:

Py2Neo (Python API)

from py2neo import Graph
g = Graph(auth=('raj','1raj23'))
query = """
  match (s:Screen)-[pm:plays_movie]->(m:Movie)
  return s.id as sid,m.id as mid,pm.date as date,pm.time as time,pm.nTickets as nticks, pm.price as price 
  order by s.id,m.id,pm.date,pm.time;
"""
res = g.run(query)
for r in res:
  #print(r.sid,r.mid,r.date,r.time,r.price)
  print(r['sid'],r['mid'],r['date'],r['time'],r['nticks'],r['price'])

See code on website for Python program to read data and create a graph database (Movie database example)