Skip to content

Update query language and SDK docs for TuringDB v3 - #19

Merged
rjb32 merged 5 commits into
mainfrom
v3-query-language-docs
Oct 16, 2026
Merged

rjb32 merged 5 commits into
mainfrom
v3-query-language-docs

Conversation

@dorukustay1

Copy link
Copy Markdown
Contributor

What

Brings the docs in line with TuringDB v3 (turingdb 3.0.x), mainly the query language, which now supports most of openCypher.

Query language (query/): the single cypher_subset page is now a group of pages. cypher_subset stays at its URL as the overview, so existing links keep working.

  • Overview (what is supported, differences from Neo4j, data types)
  • Matching patterns (MATCH, OPTIONAL MATCH, WHERE, joins, lookup by native node ID)
  • Paths (variable-length, quantified, named)
  • Results, aggregation and lists (WITH, UNION, aggregates, UNWIND, comprehensions, CASE)
  • Subqueries (EXISTS, COUNT, CALL)
  • Functions and data types
  • Writing data (CREATE, MERGE, SET, REMOVE, DELETE, changes, indexes)
  • Procedures and commands
  • Cheatsheet, rewritten

Other pages that contradicted v3

  • import_data/csv: LOAD CSV followed by MATCH works now
  • import_data/jsonl: ids may have gaps, arrays load as lists, WITH DATETIMES / WITH DURATIONS
  • import_data/gml: type-suffixed property names
  • import_data/parquet: LOAD PARQUET types and recipe
  • graph_dev/update_properties: CREATE ... SET works
  • graph_dev/*: change workflow notes, db.history() details
  • shortest-path: path is a flat list of IDs, and returning other variables fails
  • vector-search: score, TYPE HNSW, use ids directly, LOAD VECTOR file format
  • pythonsdk/reference, commands, troubles: native binary protocol, auth, embedded, errors, env vars, HTTP API
  • claude-skill, index, tutorials/create_graph

How it was checked

  • Every cypher example in query/ (248 statements) was run against a real turingdb 3.0.1 server. The remaining failures are examples that need data or files the test graph lacks (stations, my_index, a CSV).
  • Behaviour claims (functions, writes, LOAD CSV/JSONL/GML/Parquet, vector search, shortestPath, native protocol, auth, embedded) were probed against 3.0.1.
  • Where turingdb-skills and 3.0.1 disagreed, the docs follow 3.0.1 (e.g. toUpper, abs, round, sqrt, reduce and reading a key from a map bound by WITH/UNWIND all work).
  • npm run build passes (42 pages), all internal links and anchors resolve, and scripts/test-slug.mjs passes.

Please check

  • Unreleased engine changes are not documented. main in turing-db/turingdb is ahead of 3.0.1 (e.g. substring, split, keys, properties are in query/AST/FunctionDecls.cpp but are not available in 3.0.1). The docs say these are not available; they will need updating with the next release.
  • turingdb-skills is out of date on functions for the same reason (it says string and math functions do not exist).
  • The old cypher_subset page had sections (Procedures, Commands, Indexes, Extensions, UNWIND, ...) that moved to other pages, so external links to those #anchors will land at the top of the overview.
  • Timing figures (about 0.2 s for 100k nodes plus 200k edges with LOAD PARQUET, about 2.5 ms per node for a SET embedding loop) come from the skills repo and were not re-measured.
  • data_dir="~/.turing" in the SDK docs was wrong: the embedded backend does not expand ~ and created a literal ~ directory. Examples now use an absolute path.

Split the single Cypher page into a Query Language group (overview,
matching, paths, results/aggregation, subqueries, functions/types,
writing, procedures/commands) and refresh the cheatsheet. Examples were
run against turingdb 3.0.1.

Also update pages that contradicted v3: LOAD CSV + MATCH now works,
CREATE ... SET works, edgeType() is now type(), UNWIND/aggregates are
unrestricted, JSONL ids may have gaps and arrays load as lists, GML
property naming, shortestPath output format, vector search (score,
HNSW, use ids directly), LOAD PARQUET types, and the SDK's native
binary protocol (USE_TURING_PROTO), auth, embedded data_dir (no ~
expansion) and error handling.
Comment thread query/aggregation.mdx Outdated
```

<Note>
Expressions in a `WITH` must be aliased: `WITH n.name AS name`. `RETURN` does not need aliases.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this block

Comment thread query/aggregation.mdx Outdated
```

```cypher
MATCH (n:Person) RETURN count(*), count(n.age), sum(n.age), avg(n.age), min(n.age), max(n.age)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add spaces in long code blocks and breathing space by adding blank lines. + indent clauses properly

Comment thread query/aggregation.mdx Outdated

**Rules:**

- Aggregates are **not allowed in `WHERE`**. Filter after a `WITH` instead (see above).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this sentence?

Comment thread query/aggregation.mdx Outdated

- Aggregates are **not allowed in `WHERE`**. Filter after a `WITH` instead (see above).
- Aggregates cannot be nested: `count(count(*))` is an error.
- A non-aggregated expression next to an aggregate may only use the grouping keys.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Give an example

Comment thread query/aggregation.mdx Outdated
`range(start, end[, step])` includes both bounds. Unwound nodes stay nodes, so `p.name` works after `UNWIND ns AS p`. You can also `UNWIND` a list of maps and read their keys: `UNWIND [{a: 1}, {a: 2}] AS m RETURN m.a`.

<Warning>
Query parameters (`UNWIND $list`) are not supported. Write the list into the query text instead, for example `f"UNWIND {ids} AS x ..."` in Python.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are not yet supported

Comment thread query/aggregation.mdx Outdated
RETURN [1, 2] + [3], 'a' || 'b'
```

- List literals can contain expressions, mixed types, nested lists and maps.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this point

Comment thread query/functions.mdx Outdated
**`edgeType()` was removed in v3.** Use `type(e)` to get an edge's type as a string.
</Warning>

Calling a function that does not exist fails with `Function 'X' does not exist`. Functions that are **not** available include `substring`, `split`, `replace`, `left`, `right`, `rand`, `date()`, `timestamp()`, `properties`, `keys` and `elementId`. Do that kind of post-processing in your application, and filter strings with `STARTS WITH`, `ENDS WITH` and `CONTAINS`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not yet available. Please use a more positive framing for turingdb

Comment thread query/functions.mdx Outdated

- `datetime` values are stored as microseconds since the Unix epoch, **normalised to UTC**. A date-only string means midnight, and an offset (`+02:00`) is converted to the equivalent UTC instant.
- `duration` is a signed count of microseconds. It has no month component, because a month has no fixed length. `duration(<integer>)` reads the number as microseconds.
- Arithmetic works: `datetime ± duration`, `datetime − datetime`, `duration × number`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not say arithmetic works, that should be a given. Show instead an example of arithmetic on durations

Comment thread query/matching.mdx Outdated

The second query returns `0` for people who know nobody. A `WHERE` attached to an `OPTIONAL MATCH` belongs to the optional part, so rows are kept, as in Neo4j.

<Warning>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this and file a linear ticket

Comment thread query/matching.mdx Outdated

Property constraints in a pattern, `MATCH (n {name: 'Matt', age: 20})`, are exactly equivalent to the same equality tests in `WHERE`.

<Warning>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not yet supported

Comment thread query/writing.mdx Outdated

Keep each query to a few thousand rows at most.

## Property indexes

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove any talk of property indexes for now

Comment thread tutorials/create_graph.mdx Outdated
## Key Points

1. **Single CREATE Query**: Due to TuringDB's current Cypher limitations, the entire graph must be created in a single CREATE statement.
1. **Single CREATE Query**: This tutorial builds the whole graph in one `CREATE` statement, which lets the edges refer to the nodes by variable. You can also create the nodes first, `COMMIT`, and then `MATCH` them to create the edges, see [Writing data](/query/writing). To import a GML file as-is, use [`LOAD GML`](/import_data/gml).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not advertise GML now. Use one single create statement or LOAD PARQUET or LOAD JSONL

- Reformat all query examples: one clause per line, continuation lines
  indented, blank lines between statements.
- Aggregation: drop the WITH alias note and the list-literals point, explain
  filtering on an aggregate and mixing properties with aggregates (with
  examples), reword the parameters note.
- Functions: positive "not yet available" wording, replace the arithmetic
  sentence with duration arithmetic examples.
- Matching: remove the optional-node warning, reword the regex note.
- Remove property index documentation for now.
- Tutorial: point to LOAD PARQUET / LOAD JSONL instead of LOAD GML.
Comment thread commands.mdx Outdated
| `-auth-on` | Require a bearer token on every request. The token is read from the `TURINGDB_AUTH_TOKEN` environment variable, and startup fails if it is not set | off |
| `-start-timeout <ms>` | Time to wait for daemon readiness | `500` |

Flags use a **single dash** (`-demon`, not `--demon`).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remove

Comment thread graph_dev/update_properties.mdx Outdated
```

<Warning>
Each property name has a single type across the whole graph, so `SET n.age = 'old'` fails if `age` is an Integer. Labels cannot be changed after creation: `SET n:Label` is not supported. `SET n += {...}` and `SET n = {...}` are not supported either. See [Writing data](/query/writing#set-and-remove) for the full rules.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just say that labels can not be changed in another sentence below the warning block. Do not detail what is not supported

Comment thread import_data/csv.mdx Outdated
| `AS <row>` | Variable bound to each row |

All values come back as **strings** — wrap them in `toInteger(...)` / `toFloat(...)` if you need numbers.
All values come back as **strings**. Wrap them in `toInteger(...)` / `toFloat(...)` / `datetime(...)` if you need other types. Files must be comma-separated: `FIELDTERMINATOR` and the Neo4j form `LOAD CSV WITH HEADERS FROM 'file:///...'` are not supported.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the second sentence starting by Fields must

Comment thread import_data/csv.mdx Outdated
LIMIT 5
```

Without `WITH HEADERS`, the header line comes back as an ordinary data row. A row cannot be returned whole: read its fields as `row.col` or `row[<literal index>]`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Be nicer to TuringDB, remove the proposition saying that rows can not be returned and just start with row indexing

Comment thread import_data/jsonl.mdx Outdated
Each spec is `{"<property name>", <dimension>}`. The dimension must be **greater than 1**, and every array under that property must have exactly that many numeric elements (otherwise the load fails). This works for both node and relationship properties. Array properties not listed in `WITH EMBEDDINGS` are stored as Lists.

<Note>
When an import fails, the details are written to `<turing-dir>/logs/turingdb.log`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The details are written -> additional details are written

Comment thread import_data/parquet.mdx Outdated
# `LOAD PARQUET`

`LOAD PARQUET` queries may be used to load a graph into TuringDB. The command is of the following format:
`LOAD PARQUET` is the fastest way to get data into TuringDB, and the recommended path for anything beyond a few thousand entities. Above roughly 5,000 nodes or 1,000 edges, write your data to Parquet and load it with this command: 100,000 nodes and 200,000 edges load in about 0.2 seconds, whereas Cypher-driven loads (`LOAD CSV` or `UNWIND` with `MATCH` and `CREATE` for the edges) take minutes at a few thousand edges.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

End this block of text at a few thousand entities

Comment thread import_data/parquet.mdx Outdated
- `INT64`
- `DOUBLE`
- `BYTE_ARRAY` with exactly 0 levels of nesting
`INT32` and `FLOAT` columns are rejected (for example `Node column was not of type INT64` or `Unsupported column type`), so cast them to `int64` / `float64` first. To load an `INT64` column of microseconds as a `Duration`, name it in `WITH DURATIONS [<column>]`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this phrase

@rjb32
rjb32 merged commit 20b139a into main Oct 16, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants