MATCH: Pattern Matching
MATCH (n) RETURN n
MATCH (n:Person {name: 'Alice'}) RETURN n.age
MATCH (a:Person)-->(b:Company) RETURN a.name, b.name()→ Node[]→ Edge-→ Undirected edge- Node labels:
:Label- e.g.(n:Person) - Edge types:
:EDGE_TYPE- e.g.-[:KNOWS]->(one edge type per edge) - Properties:
{key: 'value', age: 30}
CREATE: Add Nodes & Edges
CREATE (:Person {name: 'Alice', age: 30})
CREATE (:Person {name: 'Mick'})-[:FRIEND_OF]->(:Person {name: 'John'})
CREATE (a)-[:EDGE]->(b), (b)-[:EDGE]->(c), (c)-[:EDGE]->(a)
CREATE (gabby:Person {name: 'Gabby', age: 27}),
(susan:Person {name: 'Susan', age: 35}),
(lynette:Person {name: 'Lynette', age: 41}),
(bree:Person {name: 'Bree', age: 42}),
(gabby)-[FRIEND_OF]->(susan),
(gabby)-[FRIEND_OF]->(lynette),
...- Labels required for node creation
- No
RETURNclause - Use commas to create multiple items at once
MATCH + CREATE and MATCH + CREATE + RETURN
// Create two nodes Person
CREATE (:Person {name: 'Alice', age: 24}),
(:Person {name: 'John', age: 27})
// Match two nodes to create the edge between them
MATCH (n:Person {name: 'Alice'}), (m:Person {name: 'John'})
CREATE (n)-[:FRIENDS_WITH]->(m)
// RETURN clause can also be added
MATCH (n:Person {name: 'Alice'}), (m:Person {name: 'John'})
CREATE (n)-[:FRIENDS_WITH]->(m)
RETURN n.name, n.age, m.name, m.ageSET: Update Properties
// Update a single property
MATCH (n:Person {name: 'Alice'})
SET n.age = 30
// Update multiple properties at once
MATCH (n:Person {name: 'Alice'})
SET n.position = 'Developer', n.surname = 'Taylor'
// Update from an expression
MATCH (p:Product)
SET p.discountPrice = p.price * (1 - 0.15)
// Update edge property
MATCH (n:Person {name: 'Alice'})-[e:KNOWS]->(m:Person {name: 'Bob'})
SET e.since = 2020
// Set an embedding vector
MATCH (n:Person {name: 'Alice'})
SET n.emb = (1.2, 2.0, 0.0, 12.0)
// Set an embedding vector by node ID
MATCH (n) WHERE n = 1234
SET n.emb = (1.2, 2.0, 0.0, 12.0)
// Conditional update with WHERE
MATCH (n:Person)
WHERE n.age < 18
SET n.isMinor = true- Always used with
MATCH, notCREATE - Creates the property if it does not already exist
- Use
COMMITto persist changes
WHERE: Filter nodes and edges by properties
To filter on node label:
MATCH (n)
WHERE n:Person
RETURN n, n.ageTo filter on node property:
MATCH (n)
WHERE n.name = 'Alice'
RETURN n, n.ageTo filter on edge label:
MATCH (n)-[e]->(m)
WHERE e:PLAY_POKER_TOGETHER
RETURN n.name, m.ageTo filter on edge property:
MATCH (n)-[e]->(m:Person)
WHERE n.name = 'Gabby'
AND e.play_poker_together = true
RETURN n.name, m.ageEdge type filtering
// Match only edges of a given type
MATCH (n:Person)-[:KNOWS]->(m:Person) RETURN n.name, m.name
// Name the edge to also return its properties
MATCH (n:Person)-[e:KNOWS]->(m:Person) RETURN n.name, e.since, m.name
// One edge type per hop
MATCH (a:Person)-[:KNOWS]->(b:Person)-[:WORKS_AT]->(c:Company) RETURN a.name, b.name, c.name
// List the edge types in the graph
CALL db.edgeTypes()- An edge has exactly one edge type, so a pattern takes a single
[:EDGE_TYPE]constraint
SKIP and LIMIT
// Return first 10 results
MATCH (n) RETURN n LIMIT 10
// Pagination: skip 10, return next 10
MATCH (n) RETURN n SKIP 10 LIMIT 10ORDER BY
// Sort ascending (default)
MATCH (n:Person) RETURN n.name, n.age ORDER BY n.age
// Sort descending
MATCH (n:Person) RETURN n.name, n.age ORDER BY n.age DESC
// Sort by multiple properties
MATCH (n:Person) RETURN n.name, n.age, n.city ORDER BY n.city, n.age DESC
// Combined with pagination
MATCH (n:Person) RETURN n.name, n.age ORDER BY n.age DESC SKIP 10 LIMIT 10Joins and Cartesian Products
// Cartesian product: all combinations of Person × Interest
MATCH (a:Person), (b:Interest) RETURN a.name, b.name
// Three-way cartesian product
MATCH (p:Person), (i:Interest), (c:Category) RETURN p.name, i.name, c.name
// Join on shared variable: persons sharing an interest
MATCH (a:Person)-->(b:Interest)<--(c:Person)
WHERE a.name <> c.name
RETURN a.name, b.name, c.name
// With explicit edge types
MATCH (a:Person)-[:INTERESTED_IN]->(b:Interest)<-[:INTERESTED_IN]-(c:Person)
WHERE a.name <> c.name
RETURN a.name, b.name, c.name
// Multi-hop join
MATCH (a:Person)-->(i:Interest)-->(c:Category)
RETURN a.name, i.name, c.name
// Mix path + cartesian product
MATCH (a:Person)-->(i:Interest), (c:Category)
WHERE c.name = 'Cat1'
RETURN a.name, i.name, c.name
// Two independent paths (cartesian of each path's results)
MATCH (a:Person)-->(i1:Interest), (b:Person)-->(i2:Interest)
WHERE a.name <> b.name
RETURN a.name, i1.name, b.name, i2.name- Comma
,separates independent patterns - Shared variables between patterns create joins
- Unrelated patterns create cartesian products (N × M rows)
Property Match Operators
MATCH (n {name: 'Alice'}) RETURN n
// exact equivalent of
MATCH (n) WHERE n.name = 'Alice' RETURN n:→ exact match using property filter in node directly=→ exact match using property filter in WHERE clause
Boolean operators
-
ORMATCH (n:Person) WHERE n.medication = "Aspirin" OR n.medication = "Ibuprofen" RETURN n.name -
ANDMATCH (n) WHERE n.name = 'Matt' AND n.age = 20 AND n.hasPhD = false RETURN n
Comparison operators
-
Equal:
=# Find antibodies targeting proteins in Human MATCH (ab:Antibody)-->(prot:Protein) WHERE prot.host = 'Human' RETURN ab.name, prot.name -
Inequal:
<># Find antibodies (associated to a protein) used together # in same publication (2-hop) MATCH (ab1:Antibody)-->(prot:Protein), (ab2:Antibody)-->(prot:Protein) WHERE ab1.name <> ab2.name RETURN ab1.name, ab2.name, prot.name, prot.gene_name -
Less than:
< -
Less than or equal to:
<= -
Greater than:
> -
Greater than or equal to:
>=# Publications published on 2020 or after MATCH (pub:Publication) WHERE pub.published_year >= 2020 RETURN pub.displayName, pub.pubmedid, pub.published_year, pub.country -
is null:
IS NULL -
is not null:
IS NOT NULL# Publications from the United States MATCH (pub:Publication) WHERE pub.country = 'United States' AND pub.institution IS NOT NULL RETURN pub.displayName, pub.institution, pub.published_year
Data Types
| Type | Example |
|---|---|
| String | 'hello' or "hello" |
| Integer | age=30 |
| Boolean | flag=true |
| Double | score=3.14 |
| Embedding | emb=(1.2, 2.0, 0.0) |
RETURN Clause
MATCH (n)-->(m) RETURN n.name, n.age, m.name, m.age- Select fields with
RETURN n.prop, m.prop
Expression evaluation
// Multiply property by constant
MATCH (n) RETURN n.price * 1.1
// Divide two properties
MATCH ()-[r]->() RETURN r.a / r.b
// Add two properties
MATCH (n) RETURN n.val + n.taxLOAD graphs
Load TuringDB graph
Files have to be available in graphs subdirectory of turing-dir.
LOAD GRAPH graph_nameLoad external data into TuringDB graph
Files have to be available in data subdirectory of turing-dir.
LOAD GML 'mygml.gml' AS my_graphLOAD JSONL 'myjsonl.jsonl' AS my_graphProcedures (CALL)
| Query | Description |
|---|---|
CALL db.labels() | All node labels |
CALL db.propertyTypes() | All node/edge property keys & types |
CALL db.edgeTypes() | All edge types |
CALL db.history() | Commit history |
CALL db.describeCommit('<hash>') | Counts for a single commit |
CALL db.procedures() | List available procedures |
CALL db.showIndexes() | List property indexes |
Procedure outputs can be YIELDed and chained: CALL db.labels() YIELD label MATCH (n) WHERE n.name = label RETURN n.
DELETE
// Delete a node
MATCH (n:Person {name: 'Alice'}) DELETE n
// Delete an edge
MATCH (n)-[e:KNOWS]->(m) DELETE eVariable-length paths
// Postfix quantifiers (not Neo4j's -[*1..3]-)
MATCH (a:Person)-[e]->+(b:Person) RETURN a, b // one or more hops
MATCH (a:Person)-[e]->*(b:Person) RETURN a, b // zero or more hops
MATCH (a:Person)-[e]->{2,4}(b:Interest) RETURN a, b // 2 to 4 hopsGraph algorithms
| Function | Description |
|---|---|
shortestPath(n, m, distanceProperty, distOutputVar, pathOutputVar) | Shortest path between nodes using the Dijkstra processor |
Functions
| Function | Description |
|---|---|
labels(n) | Node label as a string |
edgeType(e) | Edge type as a string |
toInteger(expr) | Parses a string as an integer |
toFloat(expr) | Parses a string as a float |
toBoolean(expr) | Parses a string as a boolean |
cosine_similarity(a, b) | Cosine similarity of two embeddings |
euclidean_distance(a, b) | Euclidean distance of two embeddings |
Aggregate Functions
| Function | Description |
|---|---|
count(expr) | Returns the number of non-null rows in the column corresponding to expr |
avg(expr) | Returns the average value of non-null rows in the numeric-valued column corresponding to expr |
// Introspection
MATCH (n)-[e]->(m) RETURN labels(n), edgeType(e)
// Type conversion
MATCH (n) WHERE n.year > toInteger("2020") RETURN n.name
MATCH (n) RETURN n.price * toFloat("1.07")
// Aggregation
MATCH (n:Person) RETURN count(*)Engine Commands
| Command | Description |
|---|---|
CREATE GRAPH <name> | Create a new named graph |
LOAD GRAPH <name> | Load an existing graph |
LOAD GML 'mygraph.gml' AS my_graph | Load the specified GML as TuringDB graph. Requires the GML to be accessible in TuringDB directory (-turing-dir, data subdir) |
LOAD JSONL 'mygraph.jsonl' AS my_graph | Load the specified JSONL as TuringDB graph. Requires the JSONL to be accessible in TuringDB directory (-turing-dir, data subdir) |
COMMIT | Persist intermediate state within a change (needed between separate node/edge create steps) |
LOAD COMMIT '<hash>' | Load a past commit into memory (needed for REST API queries on non-HEAD commits; CLI and SDK do this automatically) |
LIST GRAPH | List all available graphs |
HISTORY | Show commit history (versioning) |
CHANGE NEW | Create a new isolated change |
CHANGE SUBMIT | Merge current change into main |
CHANGE DELETE | Delete current change |
CHANGE LIST | List active uncommitted changes |
CREATE VECTOR INDEX <name> WITH DIMENSION <n> METRIC <COSINE|EUCLID> | Create a vector index |
VECTOR SEARCH IN <index> FOR <k> (<vec>) YIELD ids | k-nearest-neighbor vector search |
SHOW VECTOR INDEXES / DELETE VECTOR INDEX <name> | List / delete vector indexes |
CREATE INDEX <name> FOR (n) ON n.prop / FOR [e] ON e.prop | Create a property index (write; commit to take effect) |
DROP INDEX <name> | Drop a property or vector index |
MERGE_DATAPARTS | Compact the current graph’s DataParts into one |
INSTALL <ext> / SHOW EXTENSIONS / SHOW PROCEDURES | Load a procedure extension / list extensions / list procedures |
LOAD CSV "<file>" [WITH HEADERS] [ON ERROR SKIP|FAIL] AS row | Stream CSV rows (see CSV import) |
UNWIND
// Expand a literal list into rows (literal lists only)
UNWIND [1, 2, 3] AS x RETURN x
// Return a list literal directly
RETURN [1, 2, 3] AS numsProperty indexes
// Indexes are writes — create inside a change, then commit
CHANGE NEW
CREATE INDEX age_index FOR (n) ON n.age
CHANGE SUBMIT
MATCH (n) WHERE n.age = 30 RETURN n // optimizer uses the index
DROP INDEX age_index // removeUseful Patterns
// Two-hop connection
MATCH (a)-[r1]->(b)-[r2]->(c) RETURN c
// All people named John
MATCH (n:Person {name: 'John'}) RETURN n
/// exact equivalent of
MATCH (n:Person) WHERE n.name = 'John' RETURN n
// Find co-authors: two persons linked to the same publication
MATCH (a:Person)-->(p:Publication)<--(b:Person)
WHERE a.name <> b.name
RETURN a.name, b.name, p.title
// Match existing nodes then create edge between them
MATCH (n:Person {name: 'Alice'}), (m:Person {name: 'Bob'})
CREATE (n)-[:KNOWS]->(m)
// Cartesian: pair every person with every city
MATCH (p:Person), (c:City) RETURN p.name, c.name
