TuringDB home pagelight logodark logo
  • Discord
  • GitHub
  • Website
TuringDB

Get Started

  • Introduction
  • Get Started
  • Claude Code Skill
  • Commands

Concepts

  • Overview
  • A Columnar Graph Database
  • Versioning System
  • The DataPart System
  • Zero-Locking Architecture
  • Snapshots Isolation

Benchmarks

  • Results Summary
  • Technical Report

Query Language

  • Overview
  • Matching
  • Paths
  • Results and Aggregation
  • Subqueries
  • Functions and Types
  • Writing Data
  • Procedures and Commands
  • CheatSheet

Importing data

  • JSONL
  • CSV
  • Neo4j
  • GML
  • Parquet

Graph Development

  • Create Graph
  • Load Graph
  • Load External data
  • Create a Change
  • List Changes
  • Create Nodes and Edges
  • Update Properties
  • Submit a Change
  • Time Travel
  • Graph Examples

Vector Search

  • Vector Search

Graph Algorithms

  • Shortest Path

Tutorials

  • Example Notebooks

Python SDK

  • Get Started
  • Reference

Troubleshooting

  • Troubleshooting

  • EXISTS
  • COUNT
  • CALL subqueries
Query Language

Subqueries

Use EXISTS, COUNT and CALL subqueries to filter, count and compute per-row results in TuringDB.

These examples use the sample graph from the matching page.

​
EXISTS

EXISTS { ... } tests whether a pattern, or a full MATCH with its own WHERE, has at least one match for the current row. It works in WHERE and as a returned value:

MATCH (p:Person)
WHERE EXISTS { (p)-[:WORKS_AT]->(:Company {name: 'Acme'}) }
RETURN p.name

MATCH (p:Person)
WHERE EXISTS {
  MATCH (p)-[:KNOWS]->(f)
  WHERE f.age > p.age
}
RETURN p.name

MATCH (p:Person)
WHERE NOT EXISTS { (p)-[:KNOWS]->() }
RETURN p.name

MATCH (p:Person)
RETURN p.name, EXISTS { (p)-[:LIKES]->() } AS likesSomething

​
COUNT

COUNT { ... } returns the number of matches for each row:

MATCH (p:Person)
RETURN p.name, COUNT { (p)-[:KNOWS]->() } AS outDegree
ORDER BY outDegree DESC

MATCH (p:Person)
WHERE COUNT {
  MATCH (p)-[:KNOWS]-(x)
  RETURN x
} >= 2
RETURN p.name

​
CALL subqueries

A CALL { ... } subquery runs once per incoming row. It is the way to compute a per-row top-k or a per-row aggregate. Import the outer variables either in the CALL (p) header or with a WITH p as the first clause of the body:

MATCH (p:Person)
CALL (p) {
  MATCH (p)-[:KNOWS]->(f)
  RETURN f.name AS friend
  ORDER BY f.name LIMIT 1
}
RETURN p.name, friend

MATCH (p:Person)
CALL {
  WITH p
  MATCH (p)-[:KNOWS]->(f)
  RETURN count(f) AS deg
}
RETURN p.name, deg

MATCH (p:Person)
OPTIONAL CALL (p) {
  MATCH (p)-[:WORKS_AT]->(c)
  RETURN c.name AS co
}
RETURN p.name, co

CALL {
  MATCH (p:Person)
  RETURN p.name AS nm
  UNION
  MATCH (c:Company)
  RETURN c.name AS nm
}
RETURN nm
ORDER BY nm
  • Dropped rows. A non-optional CALL drops the outer rows for which its body returns nothing. Use OPTIONAL CALL to keep them with null values.
  • Imported variables. To return an imported variable from a CALL body, give it an alias: RETURN p AS me.
  • A CALL body can contain UNION, aggregation, ORDER BY and LIMIT. Write-only subqueries also work inside a change.

COLLECT { ... }, CALL (*) { }, CALL { } IN TRANSACTIONS and OPTIONAL CALL on a procedure are not yet available. To collect values, use collect() in a CALL body or a pattern comprehension.

Results and AggregationFunctions and Types
githublinkedinyoutubediscord