Neo4j API Overview
Neo4j is a graph database management system designed to handle large-scale, highly interconnected data. It enables users to model data as nodes (entities) and relationships (connections) with associated properties.
This notebook covers:
- Setting up and connecting to a Neo4j server
- Creating nodes with labels and properties
- Creating relationships between nodes
- Write clauses: MERGE, SET, DELETE
- Read clauses: MATCH, OPTIONAL MATCH, WHERE, COUNT
- Visualizing a graph with NetworkX

%load_ext autoreload
%autoreload 2
%matplotlib inlineimport logging
import neo4j as nj
import py2neo as pyneo
import helpers.hdbg as hdbg
import helpers.hnotebook as hnotebo
import tutorials.tutorial_neo4j.neo4j_utils as ttneouti
hdbg.init_logger(verbosity=logging.INFO)
_LOG = logging.getLogger(__name__)
hnotebo.config_notebook()1. Starting the Neo4j Server¶
Neo4j uses the following default ports:
7474: HTTP port for Neo4j Browser and REST API7687: Bolt protocol port for database queries7473: HTTPS port (optional)
Start the server with:
sudo neo4j start# Start the Neo4j server inside the Docker container.
!sudo neo4j start2. Connecting to the Server¶
Use the Bolt protocol URI and authentication credentials to connect.
Key functions:
GraphDatabase.driver(URI, auth=(USER, PASSWORD)): creates the driverdriver.verify_connectivity(): verifies the connection

# URI and authentication details.
URI = "neo4j://localhost:7687"
USER = "neo4j"
PASSWORD = "neo4j"
# Create a driver instance.
driver = nj.GraphDatabase.driver(URI, auth=(USER, PASSWORD))
driver.verify_connectivity()
_LOG.info("Connection established.")3. Updating the Password¶
The default credentials (neo4j/neo4j) must be changed on first use.
Once updated, the change is permanent unless you do a clean reinstallation.
Steps:
- Run the ALTER CURRENT USER Cypher command via
execute_write - Reconnect with the new password
# Change the default password.
ttneouti.change_password(driver, "neo4j", "new_password")
# Reconnect with the new password.
driver = nj.GraphDatabase.driver(URI, auth=("neo4j", "new_password"))
driver.verify_connectivity()
_LOG.info("Connection established with new password.")
# Connect to the graph using py2neo for inspection.
graph = pyneo.Graph(URI, auth=(USER, "new_password"))4. Creating Nodes¶
A node is a fundamental unit of data in Neo4j. It can have:
- Labels: categorize the node (e.g.,
Person,Employee) - Properties: key-value pairs (e.g.,
name,age,city)
The CREATE statement adds new nodes; tx.run() executes queries within
a transaction.
with driver.session() as session:
# Create a simple Person node.
session.execute_write(ttneouti.create_person, "Dave")
# Create an Employee node.
session.execute_write(ttneouti.create_node_with_label, "Employee", "Grace")
# Create a node with both Person and Employee labels.
session.execute_write(
ttneouti.create_node_with_multiple_labels, ["Person", "Employee"], "Hank"
)
# Create a Person with multiple properties.
session.execute_write(
ttneouti.create_node_with_properties,
"Person",
{"name": "Ivy", "age": 28, "city": "New York"},
)
# Create a Person and get back the created node.
created_node = session.execute_write(
ttneouti.return_created_node, "Person", "Jack"
)
_LOG.info("Created node: %s", created_node)
# View all nodes and relationships.
ttneouti.view_graph(graph)# Clear the database before the next example.
with driver.session() as session:
session.execute_write(ttneouti.clear_database)5. Creating Relationships Between Nodes¶
Relationships connect two nodes with a directed edge and a type
(e.g., KNOWS, WORKS_WITH). They can also carry properties.
Pattern:
MATCH (a:Person {name: $node1_name}), (b:Person {name: $node2_name})
CREATE (a)-[:KNOWS]->(b)Example graph:
Jack--[:KNOWS]-->DaveGrace--[:WORKS_WITH {since: 2020}]-->Hank

with driver.session() as session:
# Recreate nodes for the relationships demo.
session.execute_write(ttneouti.create_person, "Dave")
session.execute_write(ttneouti.create_person, "Jack")
session.execute_write(ttneouti.create_node_with_label, "Employee", "Grace")
session.execute_write(
ttneouti.create_node_with_multiple_labels, ["Person", "Employee"], "Hank"
)
# Create a simple KNOWS relationship.
session.execute_write(
ttneouti.create_relationship, "Person", "Jack", "KNOWS", "Person", "Dave"
)
# Create a WORKS_WITH relationship with a 'since' property.
session.execute_write(
ttneouti.create_relationship_with_properties,
"Employee",
"Grace",
"WORKS_WITH",
{"since": 2020},
"Employee",
"Hank",
)
_LOG.info("Relationships created.")
ttneouti.view_graph(graph)6. Write Clauses¶
MERGE¶
Ensures the node or relationship exists:
- If it exists, it is matched
- If it doesn’t exist, it is created
SET¶
Updates properties of a node or relationship.
DELETE¶
Removes nodes or relationships.
with driver.session() as session:
# Create Alice and Bob.
session.execute_write(
ttneouti.create_node_with_properties,
"Person",
{"name": "Alice", "age": 30},
)
session.execute_write(
ttneouti.create_node_with_properties,
"Person",
{"name": "Bob", "age": 25},
)
# Create a KNOWS relationship.
session.execute_write(
ttneouti.create_relationship, "Person", "Alice", "KNOWS", "Person", "Bob"
)
# MERGE: add Charlie if not present.
session.execute_write(
ttneouti.merge_node, "Person", {"name": "Charlie", "age": 25}
)
# MERGE: add Alice-Charlie relationship.
session.execute_write(
ttneouti.merge_relationship,
"Person",
"Alice",
"KNOWS",
"Person",
"Charlie",
)
# SET: update Alice's age and add city.
session.execute_write(
ttneouti.set_properties,
"Person",
"Alice",
{"age": 31, "city": "New York"},
)
_LOG.info("Graph before deletion:")
ttneouti.view_graph(graph)
# DELETE: remove Alice-Bob relationship.
session.execute_write(
ttneouti.delete_relationship,
"Person",
"Alice",
"KNOWS",
"Person",
"Bob",
)
# DELETE: remove Bob node.
session.execute_write(ttneouti.delete_node, "Person", "Bob")
_LOG.info("Graph after deletion:")
ttneouti.view_graph(graph)7. Read Clauses¶
MATCH¶
Retrieves nodes, relationships, or paths matching a pattern.
MATCH (n) RETURN nOPTIONAL MATCH¶
Like MATCH but includes nodes with no matching relationships (returns null).
WHERE¶
Filters results by conditions.
MATCH (a:Person) WHERE a.age > 25 RETURN a.name, a.ageCOUNT¶
Aggregates by counting nodes, relationships, or paths.
with driver.session() as session:
# Find and print all nodes.
session.execute_read(ttneouti.find_all_nodes)
# Find who Grace works with.
session.execute_read(ttneouti.find_relations, "Grace")
# Optional match: persons and who they know.
session.execute_read(ttneouti.optional_match)
# Where clause: persons older than 25.
session.execute_read(ttneouti.where_clause)
# Count all Person nodes.
session.execute_read(ttneouti.count_function)8. Clean Up¶
driver.close()
_LOG.info("Connection closed.")