Neo4j Certified Professional cheat sheet
Neo4j Certified Professional · Keep the key ideas within reach.
Cypher
MATCH finds patterns; WHERE filters; RETURN projects. Clauses are chained left to right, and each clause sees the variable scope produced by the previous one.
Node pattern syntax: (variable:Label {property: value}). Relationship pattern syntax: -[variable:TYPE {property: value}]-> ; arrow direction is part of the match.
Variable-length paths: -[:TYPE*1..3]-> matches 1 to 3 hops; * means 1 or more; *0.. allows zero hops and can match the start node itself.
MERGE is match-or-create and is not atomic by itself: on a unique constraint it can raise a constraint error under concurrency, so pair it with ON CREATE / ON MATCH.
OPTIONAL MATCH behaves like a left outer join: unmatched patterns yield null for the bound variables, so filter with WHERE ... IS NULL to find missing relationships.
Aggregations: count(*), count(n), count(DISTINCT n), collect(), sum(), avg(), min(), max(). Non-aggregated grouping keys are implicit grouping columns.
WITH acts as a pipeline boundary: it projects, aggregates, orders, limits, and can filter with WHERE; variables not listed in WITH are dropped.
CALL { ... } subqueries run per incoming row (or once with CALL { ... } IN TRANSACTIONS for batched writes); UNION combines result sets and requires matching column names.
Neo4j Fundamentals
Neo4j is a native graph database using the property graph model: nodes, relationships (always directed and typed), and properties (key-value pairs on both).
Relationships are stored with direct pointers, so traversal cost depends on the number of relationships actually traversed, not on total graph size.
A relationship must have exactly one type and one start node and one end node; it can be traversed in either direction but is stored with one direction.
Labels group nodes for lookup and constraints; a node can carry multiple labels, and labels are indexed by default for fast MATCH by label.
ACID transactions are supported; writes take locks on nodes and relationships, and deadlocks are detected and one transaction is rolled back.
The default database is 'neo4j'; multi-database support means queries run against a named database, and system commands use SHOW DATABASES.
Causal clustering separates roles: leader (writes), followers (reads and replication), and read replicas; writes route to the leader.
Neo4j Browser runs Cypher interactively; EXPLAIN shows the plan without executing, PROFILE executes and reports db hits per operator.
Schema & Indexes
Uniqueness constraint syntax: CREATE CONSTRAINT name FOR (n:Label) REQUIRE n.prop IS UNIQUE; it also creates a backing index.
Existence constraint: CREATE CONSTRAINT name FOR (n:Label) REQUIRE n.prop IS NOT NULL (Enterprise Edition only).
Relationship property uniqueness: CREATE CONSTRAINT name FOR ()-[r:TYPE]-() REQUIRE r.prop IS UNIQUE (Enterprise Edition).
Node key constraint (Enterprise): REQUIRE (n.a, n.b) IS NODE KEY enforces uniqueness plus existence of all listed properties.
Range index: CREATE INDEX name FOR (n:Label) ON (n.prop); composite indexes list multiple properties and serve queries that filter on the leading properties.
Full-text and vector indexes are created with CREATE FULLTEXT INDEX ... and CREATE VECTOR INDEX ... and are queried with db.index.fulltext.queryNodes and db.index.vector.queryNodes.
SHOW INDEXES and SHOW CONSTRAINTS list schema objects; DROP INDEX name and DROP CONSTRAINT name remove them.
Indexes are only used when the query filters on the indexed label and property; a label mismatch or function applied to the property (e.g. toLower) prevents use.
Drivers
Driver URI schemes: neo4j:// routes to a cluster with routing (bolt+routing is the legacy alias); bolt:// connects directly to a single server.
The driver object is long-lived and thread-safe; sessions are short-lived and single-threaded; transactions are the unit of work.
Driver lifecycle: GraphDatabase.driver(uri, AuthTokens.basic(user, pass)) then driver.verifyConnectivity() and driver.close().
Session config: session({database: 'neo4j', defaultAccessMode: WRITE or READ, bookmarks, fetchSize}); READ sessions may be served by followers.
Result consumption is lazy: in Java use Result.stream()/list(); in Python session.run returns a Result that must be consumed before the next query on the same session.
Parameterized queries ($param) are required for user input; values are sent separately from the query text, which prevents injection and enables plan caching.
Transaction functions retry on transient errors: executeRead/executeWrite in Java and execute_read/execute_write in Python wrap retry logic.
Bookmarks propagate causal consistency: capture session.lastBookmark() after a write and pass it to the next session to guarantee read-your-writes.
Hands-on Challenges
Find shortest path: MATCH p = shortestPath((a:Person {name:'A'})-[*]-(b:Person {name:'B'})) RETURN p; use allShortestPaths for ties.
Rank by degree: MATCH (n:Person)-[:KNOWS]->(m) RETURN n.name, count(m) AS degree ORDER BY degree DESC LIMIT 10.
Recommendation pattern: MATCH (me:User {id:$id})-[:LIKES]->(x)<-[:LIKES]-(other)-[:LIKES]->(rec) WHERE NOT (me)-[:LIKES]->(rec) RETURN rec, count() ORDER BY count() DESC.
Delete safely: DETACH DELETE removes a node and its relationships; plain DELETE fails if the node still has relationships.
Remove duplicates before creating a constraint, otherwise CREATE CONSTRAINT fails; find them with MATCH (n:L) WITH n.prop AS p, count(*) AS c WHERE c > 1 RETURN p.
Paginate with SKIP and LIMIT; for stable results always pair them with ORDER BY on a unique or indexed property.
Count relationships per node with size((n)-[:TYPE]->()) or pattern comprehension [(n)-[:TYPE]->(m) | m] to collect neighbors.
Profile slow queries with PROFILE and look for AllNodesScan or CartesianProduct operators; add a label plus an index to replace the scan.