golang

Neo4j can be applied in numerous situations: when your data is highly connected, queries are starting to become long complex to read & understand
=> Neo4j can help simplify your data model

Basic queies

  • help:topic to open help
  • OPTIONAL // still show column name as null if not exist
MATCH (movie:Movie)
OPTIONAL MATCH (director:Person)-[:ACTED_IN]->(movie)<-[:DIRECTED]-(director)
RETURN movie.title, director.name
  • Multiple relationship
MATCH (person:Person)-[:ACTED_IN | WROTE | FUNDED]->(movie:Movie)
WHERE movie.title = 'Unforgiven' AND NOT (person)-[:DIRECTED]->(movie)
RETURN person, movie
  • Regex
MATCH (movie:Movie)
WHERE movie.title =~ '(?i).+The.*'
return movie
  • ORDER BY, SKIP, AS
MATCH (actor:Person)-[role:ACTED_IN]->(movie:Movie)
WHERE movie.title = 'Top Gun'
RETURN actor.name AS Name, role.earnings AS Earnt
ORDER BY role.earnings DESC
SKIP 3
  • Logo, Blog, Bookmark, Search, Nav by tech, Darkmode
  • DISTINCT, COUNT, AVG, SUM, MIN, MAX
  • toString, replace("hello", "l", "r"), trim, upper, ceil, round
MATCH (tom:Person{name: 'Tom Hanks'})
MATCH (tom)-[:HAS_CONTACT]->(person:Person)
MATCH (person)-[role:ACTED_IN]->(movie:Movie)
WHERE person.born >= 1960 and role.earnings > 10000000
RETURN person.name AS ContactName, person.born, role.earnings as Earnt
ORDER BY role.earnings DESC
  • CREATE
CREATE(cat:Cat:Animal{sound: 'Meow'})-[:GROOMS{period: 'Daily'}]->(cat),
(joe:Bunny:Animal{name: 'Joe')
  • Add relationship to existing node. UNIQUE to prevent duplicating relationship
MATCH (joe:Bunny:Animal{name: 'Joe'}),
(cat:Cat:Animal{sound: 'Meow'})
CREATE UNIQUE (joe)-[:LIKE]->(cat),
(joe)-[:LIKE]->(andrew:Fox:Animal{name: 'Andrew'})
return joe, cat, andrew

Delete

  • This delete every node with any relationship. So if there's any node with no relationships, it will remains
MATCH (n)-[rel]-() DELETE n, rel
  • This delete every node even without any relationship
MATCH (n) DELETE n
  • We can combine above code like this
MATCH (node)
OPTIONAL MATCH (node)-[rel]-()
DELETE node, rel
  • Or use DETACH to delete node and its relationship
MATCH (n) DETACH DELETE n

Update

SET, REMOVE properties, labels

MATCH (tom:Person{name: 'Tom Hanks'})
SET tom:Handsome
REMOVE tom.sex, 
	tom:Handsome // remove label Handsome
RETURN tom

SET generated value

<i>WITH</i> breaks up a query into two different parts. We use value we need from the top to generate value for the bottom

MATCH (tom:Person{name: 'Tom Hanks'})-[:HAS_CONTACT]->(contact)
WITH tom, count(contact) AS num_of_contacts
SET tom.num_of_contacts = num_of_contacts
RETURN tom

Changing relationship types

There's no built in way that allows us to simply change a relationship type.

MATCH (tom:Person{name: 'Tom Hanks'})-[orig_rel:HAS_CONTACT]->(halle:Person{name: 'Halle Berry'})
CREATE (tom)-[new_rel:NEW_CONTACT]->(halle)
SET new_rel = orig_rel // copy all properties
DELETE orig_rel
RETURN tom, halle

Working with NULL

  • NULL <> | = NULL return nothing; NULL IN [1,2,NULL] return null, so don't use operators with NULL
  • Array can insert like this WITH(['Add 1', 'Add 2'] + person.name) as destinations
  • If new element may be NULL, put it in a array
    WITH(['Add 1', 'Add 2'] + [person.name]) as destinations
  • User <i>|</i> to pipe RETURN [address in destinations WHERE address IS NOT NULL | address]
MATCH (person:Person) WHERE person.address IS NOT NULL RETURN person

MERGE

  • Use MERGE to create if not exist MERGE (lily:Person{name: 'Lily James'}) return lily
  • Use ON CREATE SET or ON MATCH SET to combine with MERGE
MERGE (location:Lacation{name: 'San Francisco'})
ON CREATE SET location.created_at = timestamp(),
location.created_by = 'MA',
location.update_count = 0
ON MATCH SET location.updated_at = timestamp(),
location.update_count = location.update_count + 1
RETURN location

Working with paths

  • If specify *0 means we're gonna get the first node back
MATCH (keanu:Person{name: 'Keanu Reeves'})-[rel:HAS_CONTACT*]->(contact) // there're between 1 and infinity HAS_CONTACT between Keanu and another node
RETURN keanu, rel, contact
LIMIT 3
  • Get path length
MATCH (keanu:Person{name: 'Keanu Reeves'})
MATCH (tom:Person{name: 'Tom Hanks})
MATCH path = shortestPath((keanu)-[:HAS_CONTACT*..20]->(tom))
RETURN path, length(path) AS path_length
```cypher
MATCH (maxtrixActor:Person)-[:ACTED_IN]->(matrix:Moive{title: 'The Matrix'}),
(topGunActor:Person)-[:ACTED_IN]->(topGun:Movie{title: 'Top Gun}),
path = shortestPath((matrixActor)-[:HAS_CONTACT*..20]->(topGunActor))
WHERE matrixActor <> topGunActor
RETURN matrix, topGun, path, length(path) AS pathLength
ORDER BY pathLength // shotest of the shotest paths
LIMIT 3