Built-in databases in Neo4j
All Neo4j servers contain a built-in database called system, which behaves differently than all other databases. The system database stores system data and you can not perform graph queries against it.
A fresh installation of Neo4j includes two databases:
-
system- the system database described above, containing meta-data on the DBMS and security configuration. -
neo4j- the default database, named using the config optiondbms.default_database=neo4j.
Query considerations
Most of the time Cypher queries are reading or updating queries, which are run against a graph. There are also administrative commands that apply to a database, or to the entire DBMS. Administrative commands cannot be run in a session connected to a normal user database, but instead need to be run within a session connected to the system database. Administrative commands execute on the system database. If an administrative command is submitted to a user database, it is rerouted to the system database.
Cypher and Neo4j transactions
All Cypher queries run within transactions. Modifications done by updating queries are held in memory by the transaction until it is committed, at which point the changes are persisted to disk and become visible to other transactions. If an error occurs - either during query evaluation, such as division by zero, or during commit, such as constraint violations - the transaction is automatically rolled back, and no changes are persisted in the graph.
In short, an updating query always either fully succeeds or does not succeed at all.
Explicit and implicit transactions
Transactions in Neo4j can be either explicit or implicit.
| Explicit | Implicit |
|---|---|
|
Opened by the user. |
Opened automatically. |
|
Can execute multiple Cypher queries in sequence. |
Can execute a single Cypher query. |
|
Committed, or rolled back, by the user. |
Committed automatically when a transactions finishes successfully. |
Queries that start separate transactions themselves, such as queries using CALL { ... } IN TRANSACTIONS, are only allowed in implicit mode. Explicit transactions cannot be managed directly from queries, they must be managed via APIs or tools.
DBMS transactions
Beginning a transaction while connected to a DBMS will start a DBMS-level transaction. A DBMS-level transaction is a container for database transactions.
A database transaction is started when the first query to a specific database is issued. Database transactions opened inside a DBMS-level transaction are committed or rolled back when the DBMS-level transaction is committed or rolled back.
DBMS transactions have the following limitations:
-
Only one database can be written to in a DBMS transaction.
-
Cypher operations fall into the following main categories:
-
Operations on graphs.
-
Schema commands.
-
Administration commands.
-
It is not possible to combine any of these workloads in a single DBMS transaction.
ACID compliance
Neo4j is fully ACID compliant. This means that:
-
Atomicity - If a part of a transaction fails, the database state is left unchanged.
-
Consistency — Every transaction leaves the database in a consistent state.
-
Isolation — During a transaction, modified data cannot be accessed by other operations.
-
Durability — The DBMS can always recover the results of a committed transaction.
Core concepts
Nodes
MATCH (n:Person {name:'Anna'})
RETURN n.born AS birthYear
Relationships
MATCH (:Person {name: 'Anna'})-[r:KNOWS WHERE r.since < 2020]->(friend:Person)
RETURN count(r) As numberOfFriends
Paths
MATCH (n:Person {name: 'Anna'})-[:KNOWS]-{1,5}(friend:Person WHERE n.born < friend.born)
RETURN DISTINCT friend.name AS olderConnections
This example uses a quantified relationship to find all paths up to 5 hops away。
Paths can also be assigned variables. For example, the below query binds a whole path pattern, which matches the SHORTEST path from Anna to another Person node in the graph with a nationality property set to Canadian. In this case, the RETURN clause returns the full path between the two nodes.
MATCH p = SHORTEST 1 (:Person {name: 'Anna'})-[:KNOWS]-+(:Person {nationality: 'Canadian'})
RETURN p

The below query searches the graph for outgoing relationships from the Tom Hanks node to any Movie nodes, and returns the relationships and the titles of the movies connected to him.
MATCH (tom:Person {name:'Tom Hanks'})-[r]->(m:Movie)
RETURN type(r) AS type, m.title AS movie
The below query uses a NOT label expression (!) to return all relationships connected to Tom Hanks that are not of type ACTED_IN.
MATCH (:Person {name:'Tom Hanks'})-[r:!ACTED_IN]->(m:Movie)
Return type(r) AS type, m.title AS movies
Finding paths
To search for patterns of a fixed length, specify the distance (hops) between the nodes in the pattern by using a quantifier ({n}).
For example, the following query matches all Person nodes exactly 2 hops away from Tom Hanks and returns the first five rows.
MATCH (tom:Person {name:'Tom Hanks'}) -- {2} (colleagues:Person)
RETURN DISTINCT colleagues.name AS name, colleagues.born AS bornIn
ORDER BY bornIn
LIMIT 5
It is also possible to match a graph for patterns of a variable length. The below query matches all Person nodes between 1 and 4 hops away from Tom Hanks and returns the first five rows.
MATCH (p:Person {name:'Tom Hanks'}) -- {1,4} (colleagues:Person)
RETURN DISTINCT colleagues.name AS name, colleagues.born AS bornIn
ORDER BY bornIn, name
LIMIT 5

The SHORTEST keyword can be used to find a variation of the shortest paths between two nodes. In this example, ALL SHORTEST paths between the two nodes Keanu Reeves and Tom Cruise are found.

The count() function calculates the number of these shortest paths.

The length() function calculates the length of each path in terms of traversed relationships.


Finding recommendations
The following query tries to recommend co-actors for Keanu Reeves, who he has yet to work with but who his co-actors have worked with. The query then orders the results by how frequently a matched co-co-actor has collaborated with one of Keanu Reeves' co-actors.
MATCH (keanu:Person {name: "Keanu Reeves"}) - [:ACTED_IN] -> (m1:Movie) <- [:ACTED_IN] - (coActors:Person),
(coActors:Person) - [:ACTED_IN] -> (m2:Movie) <- [:ACTED_IN] - (coCoActors:Person)
WHERE NOT (keanu) - [:ACTED_IN] -> () <- [:ACTED_IN] - (coCoActors) AND keanu <> coCoActors
RETURN coCoActors.name AS recomended, count(coCoActors) AS strength
ORDER BY strength DESC
LIMIT 7
╒═════════════════╤════════╕ │recomended │strength│ ╞═════════════════╪════════╡ │"Tom Hanks" │4 │ ├─────────────────┼────────┤ │"Natalie Portman"│3 │ ├─────────────────┼────────┤ │"Stephen Rea" │3 │ ├─────────────────┼────────┤ │"John Hurt" │3 │ ├─────────────────┼────────┤ │"Halle Berry" │3 │ ├─────────────────┼────────┤ │"Jim Broadbent" │3 │ ├─────────────────┼────────┤ │"Ben Miles" │3 │ └─────────────────┴────────┘
There are several connections between the Keanu Reeves and Tom Hanks nodes in the movie database, but the two have never worked together in a film. The following query matches coactors who could introduce the two, by looking for co-actors who have worked with both of them in separate movies:
MATCH (keanu:Person {name: "Keanu Reeves"}) - [:ACTED_IN] -> (:Movie) <- [:ACTED_IN] - (coActors:Person),
(tom:Person {name: "Tom Hanks"}) - [:ACTED_IN] -> (:Movie) <- [:ACTED_IN] - (coActors:Person)
RETURN coActors.name AS coActors, count(coActors) AS strength
ORDER BY strength DESC
╒═════════════════╤════════╕ │coActors │strength│ ╞═════════════════╪════════╡ │"Hugo Weaving" │3 │ ├─────────────────┼────────┤ │"Charlize Theron"│1 │ └─────────────────┴────────┘
Cypher expressions
General
-
A variable:
n,x,rel,myFancyVariable,`A name with special characters in it[]!`. -
A property:
n.prop,x.prop,rel.thisProperty,myFancyVariable.`(special property name)`. -
A dynamic property:
n["prop"],rel[n.city + n.zip],map[coll[0]]. -
A parameter:
$param,$0. -
A list of expressions:
['a', 'b'],[1, 2, 3],['a', 2, n.property, $param],[]. -
A function call:
length(p),nodes(p). -
An aggregate function call:
avg(x.prop),count(*). -
A path-pattern:
(a)-[r]->(b),(a)-[r]-(b),(a)--(b),(a)-->()<--(b). -
An operator application:
1 + 2,3 < 4. -
A subquery expression:
COUNT {},COLLECT {},EXISTS {},CALL {}. -
A regular expression:
a.name =~ 'Tim.*'. -
A
CASEexpression. -
null.

String literal escape sequences
String literals can contain the following escape sequences:
| Escape sequence | Character |
|---|---|
|
|
Tab |
|
|
Backspace |
|
|
Newline |
|
|
Carriage return |
|
|
Form feed |
|
|
Single quote |
|
|
Double quote |
|
|
Backslash |
|
|
Unicode UTF-16 code point (4 hex digits must follow the |
Conditional expressions (CASE)
Generic conditional expressions can be expressed in Cypher® using the CASE construct. Two variants of CASE exist within Cypher: the simple form, to compare a single expression against multiple values, and the generic form, to express multiple conditional statements.


CREATE
(alice:Person {name:'Alice', age: 38, eyes: 'brown'}),
(bob:Person {name: 'Bob', age: 25, eyes: 'blue'}),
(charlie:Person {name: 'Charlie', age: 53, eyes: 'green'}),
(daniel:Person {name: 'Daniel', eyes: 'brown'}),
(eskil:Person {name: 'Eskil', age: 41, eyes: 'blue'}),
(alice)-[:KNOWS]->(bob),
(alice)-[:KNOWS]->(charlie),
(bob)-[:KNOWS]->(daniel),
(charlie)-[:KNOWS]->(daniel),
(bob)-[:MARRIED]->(eskil)
Simple CASE
The simple CASE form is used to compare a single expression against multiple values, and is analogous to the switch construct of programming languages. The expressions are evaluated by the WHEN operator until a match is found. If no match is found, the expression in the ELSE operator is returned. If there is no ELSE case and no match is found, null will be returned.
Syntax
CASE test WHEN value [, value]* THEN result [WHEN ...] [ELSE default] END
Example
MATCH (n:Person) RETURN CASE n.eyes WHEN 'blue' THEN 1 WHEN 'brown', 'hazel' THEN 2 ELSE 3 END AS result, n.eyes
Extended SimpleCASE
The extended simple CASE form allows the comparison operator to be specified explicitly. The simple CASE uses an implied equals (=) comparator.
The supported comparators are:
-
Regular Comparison Operators:
=,<>,<,>,<=,>= -
IS NULLOperator:IS [NOT] NULL -
Type Predicate Expression:
IS [NOT] TYPED <TYPE>(Note that the formIS [NOT] :: <TYPE>is not accepted) -
Normalization Predicate Expression:
IS [NOT] NORMALIZED -
String Comparison Operators:
STARTS WITH,ENDS WITH,=~(regex matching)
Syntax
CASE test WHEN [comparisonOperator] value [, [comparisonOperator] value ]* THEN result [WHEN ...] [ELSE default] END
Example
MATCH (n:Person) RETURN n.name, CASE n.age WHEN IS NULL, IS NOT TYPED INTEGER | FLOAT THEN "Unknown" WHEN = 0, = 1, = 2 THEN "Baby" WHEN <= 13 THEN "Child" WHEN < 20 THEN "Teenager" WHEN < 30 THEN "Young Adult" WHEN > 1000 THEN "Immortal" ELSE "Adult" END AS result
Generic CASE
The generic CASE expression supports multiple conditional statements, and is analogous to the if-elseif-else construct of programming languages. Each row is evaluated in order until a true value is found. If no match is found, the expression in the ELSE operator is returned. If there is no ELSE case and no match is found, null will be returned.
Syntax
CASE WHEN predicate THEN result [WHEN ...] [ELSE default] END
Example
MATCH (n:Person) RETURN CASE WHEN n.eyes = 'blue' THEN 1 WHEN n.age < 40 THEN 2 ELSE 3 END AS result, n.eyes, n.age
CASE with null values
When working with null values, you may be forced to use the generic CASE form. The two examples below use the age property of the Daniel node (which has a null value for that property) to clarify the difference.
CASEMATCH (n:Person) RETURN n.name, CASE n.age WHEN null THEN -1 ELSE n.age - 10 END AS age_10_years_ago

╒═════════╤════════════════╕ │n.name │age_10_years_ago│ ╞═════════╪════════════════╡ │"Alice" │28 │ ├─────────┼────────────────┤ │"Bob" │15 │ ├─────────┼────────────────┤ │"Charlie"│43 │ ├─────────┼────────────────┤ │"Daniel" │null │ ├─────────┼────────────────┤ │"Eskil" │31 │ └─────────┴────────────────┘
Generic CASE
MATCH (n:Person) RETURN n.name, CASE WHEN n.age IS NULL THEN -1 ELSE n.age - 10 END AS age_10_years_ago

╒═════════╤════════════════╕ │n.name │age_10_years_ago│ ╞═════════╪════════════════╡ │"Alice" │28 │ ├─────────┼────────────────┤ │"Bob" │15 │ ├─────────┼────────────────┤ │"Charlie"│43 │ ├─────────┼────────────────┤ │"Daniel" │-1 │ ├─────────┼────────────────┤ │"Eskil" │31 │ └─────────┴────────────────┘
CASE expressions and succeeding clauses
The results of a CASE expression can be used to set properties on a node or relationship.
MATCH (n:Person) WITH n, CASE n.eyes WHEN 'blue' THEN 1 WHEN 'brown' THEN 2 ELSE 3 END AS colorCode SET n.colorCode = colorCode RETURN n.name, n.colorCode
Further considerations
CASE result branches are statically checked prior to execution. This means that if a branch is not semantically correct, it will still throw an exception, even if that branch may never be executed during runtime.
In the following example, date is statically known to be a STRING value, and therefore would fail if treated as a DATE value.
Not allowed
WITH "2024-08-05" AS date, "string" AS type
RETURN CASE type
WHEN "string" THEN datetime(date)
WHEN "date" THEN datetime({year: date.year, month: date.month, day: date.day})
ELSE datetime(date)
END AS dateTime
ERROR: Neo.ClientError.Statement.SyntaxError
Type mismatch: expected Map, Node, Relationship, Point, Duration, Date, Time, LocalTime, LocalDateTime or DateTime but was String (line 4, column 38 (offset: 136))
" WHEN "date" THEN datetime({year: date.year, month: date.month, day: date.day})"
Clauses
Reading clauses
| Clause | Description |
|---|---|
|
Specify the patterns to search for in the database. |
|
|
Specify the patterns to search for in the database while using |
Reading sub-clauses
These comprise sub-clauses that must operate as part of reading clauses.
| Sub-clause | Description |
|---|---|
|
Adds constraints to the patterns in a |
|
|
A sub-clause following |
|
|
Defines from which row to start including the rows in the output. As of Neo4j 5.24, it can be used as a standalone clause. |
|
|
Constrains the number of rows in the output. As of Neo4j 5.24, it can be used as a standalone clause. |
Projecting clauses
These comprise clauses that define which expressions to return in the result set. The returned expressions may all be aliased using AS.
| Clause | Description |
|---|---|
|
Defines what to include in the query result set. |
|
|
Allows query parts to be chained together, piping the results from one to be used as starting points or criteria in the next. |
|
|
Expands a list into a sequence of rows. |
|
|
Defines a query to have no result. |
Writing clauses
These comprise clauses that write the data to the database.
| Clause | Description |
|---|---|
|
Create nodes and relationships. |
|
|
Delete nodes, relationships or paths. Any node to be deleted must also have all associated relationships explicitly deleted. |
|
|
Delete a node or set of nodes. All associated relationships will automatically be deleted. |
|
|
Update labels on nodes and properties on nodes and relationships. |
|
|
Remove properties and labels from nodes and relationships. |
|
|
Update data within a list, whether components of a path, or the result of aggregation. |
Reading/Writing clauses
These comprise clauses that both read data from and write data to the database.
| Clause | Description |
|---|---|
|
Ensures that a pattern exists in the graph. Either the pattern already exists, or it needs to be created. |
|
|
|
Used in conjunction with |
|
|
Used in conjunction with |
|
Invokes a procedure deployed in the database and return any results. |
Subquery clauses
| Clause | Description |
|---|---|
|
Evaluates a subquery, typically used for post-union processing or aggregations. |
|
|
Evaluates a subquery in separate transactions. Typically used when modifying or importing large amounts of data. |
Set operations
| Clause | Description |
|---|---|
|
Combines the result of multiple queries into a single result set. Duplicates are removed. |
|
|
Combines the result of multiple queries into a single result set. Duplicates are retained. |
Multiple graphs
| Clause | Description |
|---|---|
|
Determines which graph a query, or query part, is executed against. |
Importing data
| Clause | Description |
|---|---|
|
Use when importing data from CSV files. |
|
|
This clause may be used to prevent an out-of-memory error from occurring when importing large amounts of data using |
Listing functions and procedures
| Clause | Description |
|---|---|
|
List the available functions. |
|
|
List the available procedures. |
Configuration Commands
| Clause | Description |
|---|---|
|
List configuration settings. |
Transaction Commands
| Clause | Description |
|---|---|
|
List the available transactions. |
|
|
Terminate transactions by their IDs. |
Reading hints
These comprise clauses used to specify planner hints when tuning a query. More details regarding the usage of these — and query tuning in general — can be found in Planner hints and the USING keyword.
| Hint | Description |
|---|---|
|
Index hints are used to specify which index, if any, the planner should use as a starting point. |
|
|
Index seek hint instructs the planner to use an index seek for this clause. |
|
|
Scan hints are used to force the planner to do a label scan (followed by a filtering operation) instead of using an index. |
|
|
Join hints are used to enforce a join operation at specified points. |
Index and constraint clauses
These comprise clauses to create, show, and drop indexes and constraints.
| Clause | Description |
|---|---|
|
Create, show or drop an index. |
|
|
Create, show or drop a constraint. |
Administration clauses
Cypher includes commands to manage databases, aliases, servers, and role-based access control. To learn more about each of these, see:

浙公网安备 33010602011771号