# Query operations

> Operations that read rows and notes: select_rows, link targets, text and semantic search, the link graph.

Operations that read rows and notes: select_rows, link targets, text and semantic search, the link graph. The [overview](https://datanotes.dev/reference/operations/) lists every operation by kind. The MCP server, `datanotes mcp`, offers each operation as an MCP tool of the same name, and `engineTools()` of `datanotes/mcp` gives the same definitions to [your own MCP server](https://datanotes.dev/develop/build-on-datanotes/#build-your-own-mcp-server). `DatanotesClient.call(name, args)` runs one from code. Over HTTP each one is `POST /datanotes/operations/<name>/`, with its arguments as the JSON body: the [HTTP API reference](https://datanotes.dev/api/) lists them.

Every write is validated. Writes to rows and to the schema are journaled and undone with `undo_migration`; `configure_database`, the webhook operations, `vacuum_table` and `sync_semantic_index` are not journaled.

## `select_rows`

**Select Rows** · read-only

Query rows: `{table, total, rows: [{path, ...}]}`. `table` may be a view, `system.information_schema.<catalogs|schemata|tables|columns|views|check_constraints>`, or `base:<name>` — every table that extends that base (e.g. `base:record`: all event-like tables), on the base’s columns, each row tagged `_source` with its table.

* `where`: as in update_rows; relative dates `"{today}"`, `"{today-7d}"`, `"{now-24h}"` (on a date column a date-time counts by its day); file columns `file_name`, `file_link`, `file_modified`, `file_backlink_count`.
* `columns`, `order_by` (`-col` descending), `limit` (default 100, max 1000), `offset`, `expand` (inline linked rows’ frontmatter), `include_body` (the note body as `body`).
* `join`: `{"table", "on": {"date(occurred_at)+1": "date(timestamp)"}, "as", "type": "inner"|"left", "columns", "where"}` — matches attached under `as`.
* `group_by` (column, `path` or `date(col)±n`; a list column counts once per item) + `aggregates` `{"n": "count", "kcal": "sum:meal.kcal"}` (count, count:col, sum, avg, min, max).
* `this_note`: vault path of the note the result is for: `{this.*}` tokens in a view’s query and in `where` read it (`{this.date}`, `{this.link}`, `{this.name}`, `{this.path}`); without it (or a front matter key the note lacks) a token stays as written and matches no row, whatever the operator (`within` included).
* Ordered enums compare by position. Time travel: `version` (of one table) or `timestamp`. With `timestamp` a join, a view, a union or `base:<name>` reads every table in it as of that time (`versions`: the version read of each); a table that did not exist then adds no rows to a union or base. `version` is refused where several tables are read; information_schema has no history. Views and bases keep today’s definition, and links followed by `where` (`project.kind`, `within`) or `expand` read the linked rows as they are now.

Examples: [Catalogs, schemas and the database](https://datanotes.dev/guides/database-objects/catalogs-and-schemas/), [Tables](https://datanotes.dev/guides/database-objects/tables/), [Columns and types](https://datanotes.dev/guides/database-objects/columns/), [Views](https://datanotes.dev/guides/database-objects/views/), [Bases](https://datanotes.dev/guides/database-objects/bases/), [Relations and hierarchies](https://datanotes.dev/guides/database-objects/relations/), [Validation](https://datanotes.dev/guides/data-quality/validation/), [CHECK constraints](https://datanotes.dev/guides/data-quality/check-constraints/), [Hand edits](https://datanotes.dev/guides/data-quality/hand-edits/), [Read and filter rows](https://datanotes.dev/guides/read-and-write/read-and-filter/), [Joins and aggregates](https://datanotes.dev/guides/read-and-write/joins-and-aggregates/), [Write and move rows](https://datanotes.dev/guides/read-and-write/write-rows/), [Batch writes](https://datanotes.dev/guides/read-and-write/batch/), [Import existing notes](https://datanotes.dev/guides/read-and-write/import-notes/), [Journal and undo](https://datanotes.dev/guides/history/journal-and-undo/), [Table history and time travel](https://datanotes.dev/guides/history/table-history/), [Restore a table or the database](https://datanotes.dev/guides/history/restore/).

| Parameter      | Type         | Required     | Default | Description |
| -------------- | ------------ | ------------ | ------- | ----------- |
| `table`        | string       | yes          |         |             |
| `columns`      | string\[] \\ | null         |         | `null`      |
| `where`        | object \\    | null         |         | `null`      |
| `order_by`     | string \\    | string\[] \\ | null    |             |
| `limit`        | integer \\   | null         |         | `null`      |
| `offset`       | integer \\   | null         |         | `null`      |
| `expand`       | string\[] \\ | null         |         | `null`      |
| `join`         | object \\    | null         |         | `null`      |
| `group_by`     | string \\    | string\[] \\ | null    |             |
| `aggregates`   | object \\    | null         |         | `null`      |
| `include_body` | boolean      |              | `false` |             |
| `version`      | integer \\   | null         |         | `null`      |
| `timestamp`    | string \\    | null         |         | `null`      |
| `this_note`    | string \\    | null         |         | `null`      |

## `list_link_targets`

**List Link Targets** · read-only

The rows a link column may point to, for one row: what an agent or a picker offers before writing the link. A link column can filter its targets:

* `ref_where`: a `where` filter every target must match (`{"kind": {"in": ["area", "project"]}}`).
* `ref_by`: a column of the row picks the targets’ level: `{"column": "kind", "map": {"area": null, "project": ["area"], "workstream": ["project"]}}`: a workstream’s parent must have kind project; `null` is a top level (the link must stay empty); any other level needs the link; a value missing from the map is refused. `levels: ["area", "project", "workstream"]` writes the same chain short (each level’s parent is the level before it). `target_column` reads another column of the target (default: the same name). describe_table shows the expanded map. Writes refuse other targets (code `ref`, listing the valid ones), a link to the row itself (`ref`), a link to no row of the table (`broken_link`) and a missing link a level needs (`required`). Pass the row (`row`: path, link or name; a name rows in different folders share is refused, listing their paths) and/or its values (`values`, e.g. `{"kind": "workstream"}` for a new row). Returns `{rows: [{name, link, path, <level column>}], total, required, empty, reason}` (no rows, and the reason, for a level the map lacks); write a row’s `link` as the value.

Examples: [Relations and hierarchies](https://datanotes.dev/guides/database-objects/relations/).

| Parameter | Type       | Required | Default | Description                                |
| --------- | ---------- | -------- | ------- | ------------------------------------------ |
| `table`   | string     | yes      |         |                                            |
| `column`  | string     | yes      |         | A link column (or list of links) with ref. |
| `row`     | string \\  | null     |         | `null`                                     |
| `values`  | object \\  | null     |         | `null`                                     |
| `limit`   | integer \\ | null     |         | `null`                                     |

## `read_note`

**Read Note** · read-only

Read a note or another file of the vault: `{path, content, front_matter, tags, modified_at, created_at, size}`. `content` is the whole text, front matter included; `tags` are without `#`, from the text and the front matter; the times are in the database’s time zone. A missing file is an error. `path`: vault-relative, forward slashes.

Examples: [Relations and hierarchies](https://datanotes.dev/guides/database-objects/relations/), [Hand edits](https://datanotes.dev/guides/data-quality/hand-edits/), [Import existing notes](https://datanotes.dev/guides/read-and-write/import-notes/), [Read and search notes](https://datanotes.dev/guides/search/text/).

| Parameter | Type   | Required | Default | Description                                                        |
| --------- | ------ | -------- | ------- | ------------------------------------------------------------------ |
| `path`    | string | yes      |         | The file’s vault path, with its extension (“Films/Metropolis.md”). |

## `list_folder`

**List Folder** · read-only

The direct children of a vault folder: `{folder, folders, files}`, each a vault path, sorted; dot-files and dot-folders are left out. `folder` “” is the vault root. A missing folder is an error.

Examples: [Catalogs, schemas and the database](https://datanotes.dev/guides/database-objects/catalogs-and-schemas/), [Tables](https://datanotes.dev/guides/database-objects/tables/), [Columns and types](https://datanotes.dev/guides/database-objects/columns/), [Write and move rows](https://datanotes.dev/guides/read-and-write/write-rows/), [Read and search notes](https://datanotes.dev/guides/search/text/).

| Parameter | Type   | Required | Default | Description                                  |
| --------- | ------ | -------- | ------- | -------------------------------------------- |
| `folder`  | string |          | `""`    | Vault-relative folder; “” is the vault root. |

## `search_notes`

**Search Notes** · read-only

Plain-text search: every word of `query` must occur, case- and accent-insensitive, in the note’s path or text; there are no operators. Returns `{query, results: [{path, score, matches: [{start, end, context}]}], total}`, best first: at most 200 notes (`total` counts them all) and 20 matches per note. `context_length`: characters of context on each side (default 100, max 1000).

Examples: [Read and search notes](https://datanotes.dev/guides/search/text/).

| Parameter        | Type    | Required | Default | Description                                                   |
| ---------------- | ------- | -------- | ------- | ------------------------------------------------------------- |
| `query`          | string  | yes      |         |                                                               |
| `context_length` | integer |          | `100`   | Characters of context on each side of a match (at most 1000). |

## `semantic_search`

**Semantic Search** · read-only

Find notes by meaning, not exact words: `{query, results: [{path, score, heading, snippet, table?}]}`, one result per note (its best passage), best first. Use it for vague questions (“the dinner where we talked about moving”, “what did I decide about the car”) and to find the rows to read or update; then read_note / select_rows for the details. Filters: `tables` (qualified or short names), `folder`, `min_score` (cosine 0–1; \~0.5+ is usually relevant). `limit`: default 10, max 100. Fails with a clear message when semantic search is not enabled in the engine settings.

Examples: [Find notes by meaning](https://datanotes.dev/guides/search/semantic/).

| Parameter   | Type         | Required | Default | Description |
| ----------- | ------------ | -------- | ------- | ----------- |
| `query`     | string       | yes      |         |             |
| `limit`     | integer      |          | `10`    |             |
| `tables`    | string\[] \\ | null     |         | `null`      |
| `folder`    | string \\    | null     |         | `null`      |
| `min_score` | number \\    | null     |         | `null`      |

## `graph_neighbors`

**Graph Neighbors** · read-only

Direct neighbours of notes: what they link to (`out`) and what links to them (`in`, backlinks), with counts per edge label. `direction`: out, in or both (default).

`from_nodes` selects the notes: `{"paths": [...]}` and/or `{"table": ..., "where": {...}}`. Edges are labelled with their link column (`people`, `event`, …) or `link` for other links.

Examples: [Walk the link graph](https://datanotes.dev/guides/search/link-graph/).

| Parameter    | Type         | Required  | Default     | Description |
| ------------ | ------------ | --------- | ----------- | ----------- |
| `from_nodes` | object       | yes       |             |             |
| `direction`  | `"out"` \\   | `"in"` \\ | `"both"` \\ | null        |
| `edges`      | string\[] \\ | null      |             | `null`      |

## `graph_traverse`

**Graph Traverse** · read-only

Breadth-first walk over links from `from_nodes` (`{"paths": [...]}` and/or `{"table", "where"}`).

* `direction`: out (default, follow links), in (follow backlinks) or both.
* `edges`: edge labels to follow (link columns such as `people`, `event`, or `link`).
* `tables`: return only notes of these tables; `through`: only walk on through these tables.
* `min_depth` (default 1) / `max_depth` (default 2, max 10), `limit` (default 500).

Each node comes with `depth` and `via` (one shortest route). Example — moods tied to events with Alice: from `{"table": "person", "where": {"name": "Alice"}}`, direction `in`, edges `["people", "event"]`, tables `["mood"]`, max_depth 2. Feed the paths to `select_rows` with `where: {"path": {"in": [...]}}` to aggregate them.

Examples: [Walk the link graph](https://datanotes.dev/guides/search/link-graph/).

| Parameter    | Type         | Required  | Default     | Description |
| ------------ | ------------ | --------- | ----------- | ----------- |
| `from_nodes` | object       | yes       |             |             |
| `direction`  | `"out"` \\   | `"in"` \\ | `"both"` \\ | null        |
| `edges`      | string\[] \\ | null      |             | `null`      |
| `tables`     | string\[] \\ | null      |             | `null`      |
| `through`    | string\[] \\ | null      |             | `null`      |
| `min_depth`  | integer \\   | null      |             | `null`      |
| `max_depth`  | integer \\   | null      |             | `null`      |
| `limit`      | integer \\   | null      |             | `null`      |

## `graph_path`

**Graph Path** · read-only

Shortest chain of links between two sets of notes (each `{"paths": [...]}` and/or `{"table", "where"}`): `found`, `length` and `path`: the steps (`from`, `label`, `direction`, `to`). `direction` both by default; `max_depth` default 6 (max 10).

Examples: [Walk the link graph](https://datanotes.dev/guides/search/link-graph/).

| Parameter    | Type         | Required  | Default     | Description |
| ------------ | ------------ | --------- | ----------- | ----------- |
| `from_nodes` | object       | yes       |             |             |
| `to_nodes`   | object       | yes       |             |             |
| `direction`  | `"out"` \\   | `"in"` \\ | `"both"` \\ | null        |
| `edges`      | string\[] \\ | null      |             | `null`      |
| `max_depth`  | integer \\   | null      |             | `null`      |
