From c220e63828d9f83ab03d0ccdbd9634cabfd4d3cd Mon Sep 17 00:00:00 2001 From: Jack Ye Date: Mon, 28 Sep 2026 17:40:52 -0500 Subject: [PATCH] docs: split SDKs and SQL into two pages, promote to Getting Started SQL now leads with why you'd reach for it beyond analytics: it's served over Flight SQL, so it's the way in for any language without a native LanceDB SDK, and broadly every public SDK method has a corresponding SQL statement. Closes by pointing at the SQL Reference as the spec that defines the precise behavior behind both the SQL surface and the SDK operations it mirrors. Moving both into Getting Started (before Agentic Skills) means a reader knows what the API surface even is before being told how to hand it to an agent. --- docs/web/architecture.mdx | 2 +- docs/web/basics/apis.mdx | 149 ------------------------------- docs/web/basics/jobs.mdx | 2 +- docs/web/basics/lance.mdx | 4 +- docs/web/basics/limits.mdx | 2 +- docs/web/basics/query.mdx | 2 +- docs/web/basics/sdk.mdx | 99 ++++++++++++++++++++ docs/web/basics/sql.mdx | 119 ++++++++++++++++++++++++ docs/web/curation/aggregate.mdx | 2 +- docs/web/curation/index.mdx | 2 +- docs/web/curation/join.mdx | 2 +- docs/web/curation/windowing.mdx | 2 +- docs/web/docs.json | 9 +- docs/web/management/database.mdx | 2 +- docs/web/management/index.mdx | 2 +- docs/web/sql/data-types.mdx | 2 +- docs/web/sql/index.mdx | 2 +- 17 files changed, 239 insertions(+), 165 deletions(-) delete mode 100644 docs/web/basics/apis.mdx create mode 100644 docs/web/basics/sdk.mdx create mode 100644 docs/web/basics/sql.mdx diff --git a/docs/web/architecture.mdx b/docs/web/architecture.mdx index 661911f2e..d03b7ba5c 100644 --- a/docs/web/architecture.mdx +++ b/docs/web/architecture.mdx @@ -48,7 +48,7 @@ server in the picture at all. **What follows from that.** Nothing runs unless you call it — no background compaction, no server-side [jobs](/basics/jobs), no -[SQL endpoint](/basics/apis). Scale is your process's scale: a query gets the +[SQL endpoint](/basics/sql). Scale is your process's scale: a query gets the cores and memory your process has. Access control is whatever your object store enforces, since there is no other gatekeeper. diff --git a/docs/web/basics/apis.mdx b/docs/web/basics/apis.mdx deleted file mode 100644 index de3a07b1e..000000000 --- a/docs/web/basics/apis.mdx +++ /dev/null @@ -1,149 +0,0 @@ ---- -title: "SDKs and SQL" -sidebarTitle: "SDKs & SQL" -description: "The ways to reach LanceDB — the language SDKs, the SQL endpoint, the REST API — and what each can do." -icon: code-compare -keywords: ["python", "typescript", "rust", "java", "sql", "rest", "api reference", "sdk"] ---- - -The same table can be reached several ways: a language SDK, SQL, or the REST -API. They are views onto one engine, not separate products -- a table written -from Python is queried from SQL without an export step. - -They are not interchangeable, though, and the differences are worth knowing -before you pick one. - -## What each one can do {#matrix} - -| | Python | TypeScript | SQL | -| --- | :---: | :---: | :---: | -| Create and manage catalog objects | yes | yes | partly | -| Insert, merge, update, delete | yes | yes | yes | -| Filter, project, aggregate, join | yes | yes | yes | -| Vector search | yes | yes | -- | -| Full-text search | yes | yes | yes | -| Feature engineering, jobs | yes | partly | yes | -| Runs against a local database | yes | yes | **no** | - -Three entries in that table do most of the work of explaining the rest. - -## SQL needs a deployment {#sql-is-remote} - - -SQL is not available on a local database. A connection to a directory or a -bucket has no server to plan and execute a statement, and asking it to raises -`NotImplementedError`. - - -```python -db = lancedb.connect("./.lancedb") # no SQL -db = lancedb.connect("db://my-database") # SQL -``` - -This is the largest behavioural difference between the embedded and deployed -forms, and the reason the SDKs are the portable choice: SDK code moves between -the two by changing the URI, SQL does not. - -Enterprise Queries are served over an -[Arrow Flight SQL](https://arrow.apache.org/docs/format/FlightSql.html) -endpoint, so any Flight SQL client can reach it and results arrive as Arrow -record batches. - -## Vector search has no SQL form {#no-vector-sql} - -Similarity search is a query-builder operation. A query that needs both vector -similarity and SQL analytics runs the search in an SDK and the analytics over -its result. Full-text search *is* available in SQL, as the -[`fts()`](/sql/functions#fts) table function and the -[`contains_tokens`](/sql/scalar-functions#contains-tokens) predicate. - -## TypeScript has no SQL method {#ts-no-sql} - -The TypeScript SDK does not expose SQL, and has no methods for -[functions](/management/function). Reach the endpoint with a Flight -SQL client instead -- see [connecting a client](/sql#connecting). This is a gap in -the SDK rather than in the endpoint: the same statements work. - -## Running SQL from Python {#sql-from-python} - -```python -reader = db.execute_query("SELECT id, text FROM my_docs LIMIT 10") -table = reader.read_all() -``` - -`execute_query` returns a blocking Arrow reader once results start arriving; it -does not wait for the whole query. `execute_query_async` returns a handle -instead -- see [Queries](/basics/query). - -## Python multiprocessing {#multiprocessing} - - -Do not use `fork` as the start method with Python's `multiprocessing` module. -Lance is multi-threaded internally, and `fork` with alive threads is unsafe -- -use `spawn` instead. See -[this discussion](https://discuss.python.org/t/concerns-regarding-deprecation-of-fork-with-alive-threads/33555) -for why. - - -## Choosing between them {#choosing} - -Reach for **the SDKs** when you are writing data, managing the catalog, running -vector search, or building an application that should work the same embedded and -deployed. - -Reach for **SQL** when the question is analytical -- joins across tables, -aggregates, window functions -- or when the thing asking is a BI tool, a -notebook, or a person who already thinks in SQL. It is also the only way to -create a [view](/management/view). - -The two compose. A common shape is SDK code to build and maintain tables, and -SQL for the analysis on top. - -## Reference {#reference} - -### Officially supported SDKs {#supported-sdks} - -Python, TypeScript and Rust are supported against both embedded and deployed -LanceDB. - -| Reference | Description | -|:--------------|-------------------| -| [Python](https://lancedb.github.io/lancedb/python/python/) | Full-featured Python client with pandas and numpy integration | -| [TypeScript](https://lancedb.github.io/lancedb/js/) | A TypeScript wrapper around the Rust library, built with `napi-rs` | -| [Rust](https://docs.rs/lancedb/latest/lancedb/index.html) | Native Rust library with persistent storage and high performance | - -### REST API {#rest} - -Enterprise A deployment implements the -[Lance REST Namespace](/basics/lance#enterprise), so the catalog is reachable -over HTTP by anything that speaks it -- see the -[REST API reference](/api-reference/rest). - -| Reference | Description | -|:--------------|-------------------| -| [Java](https://lancedb.github.io/lancedb/java/java/) | REST API Enterprise SDK in Java | - -### Community SDKs {#community-sdks} - -Contributed by the community rather than supported by LanceDB, so feature parity -and release cadence vary. - -| Reference | Description | -|:--------------|-------------------| -| [Go](https://pkg.go.dev/github.com/lancedb/lancedb-go/pkg/lancedb) | Community-contributed Go SDK | -| [Ruby](https://github.com/scientist-labs/lancelot) | Community-contributed Ruby bindings | -| [Swift](https://github.com/RyanLisse/LanceDbSwiftKit) | Community-contributed Swift SDK | -| [R](https://github.com/CathalByrneGit/lancedb) | Community-contributed R package | -| [Flutter](https://github.com/Alexcn/flutter_lancedb) | Community-contributed Flutter bindings | - -## What stays the same {#invariants} - -Whichever you pick: - -- **Types are Arrow types.** A vector column is a `FixedSizeList` - everywhere, not a SQL type mapped onto storage. See - [Functions and types](/sql/functions). -- **Reads are Arrow.** Nothing is serialized into language objects on the way out - unless you convert it. -- **The catalog is one catalog.** A table created from TypeScript is visible to - Python and to SQL immediately -- there is no per-language namespace. diff --git a/docs/web/basics/jobs.mdx b/docs/web/basics/jobs.mdx index aa6c9cda5..a17425551 100644 --- a/docs/web/basics/jobs.mdx +++ b/docs/web/basics/jobs.mdx @@ -191,4 +191,4 @@ one with nothing behind it: `id` is `None`, `status()` reports `"finished"`, `wait()` returns immediately, `cancel()` does nothing, and `events()` raises. This is the difference to expect when moving between embedded and deployed -- -see [SDKs and SQL](/basics/apis). +see [SDKs](/basics/sdk). diff --git a/docs/web/basics/lance.mdx b/docs/web/basics/lance.mdx index 136457bfd..6552c3735 100644 --- a/docs/web/basics/lance.mdx +++ b/docs/web/basics/lance.mdx @@ -53,7 +53,7 @@ db = lancedb.connect("s3://bucket/path") There is no server, which is what makes it embedded -- and also what bounds it. There is nothing to run work on your behalf, so there are no server-side -[jobs](/basics/jobs), no [SQL endpoint](/basics/apis), and no shared catalog +[jobs](/basics/jobs), no [SQL endpoint](/basics/sql), and no shared catalog beyond what the storage layer itself provides. LanceDB OSS is Apache 2.0 licensed. LanceDB Enterprise is the commercial, @@ -73,7 +73,7 @@ db = lancedb.connect("db://my-database", api_key="...") Implementing the specification rather than inventing an interface is what makes the catalog reachable by anything that speaks it, and what makes [authorization](/governance/authorization), server-side jobs, and -[SQL](/basics/apis) possible: there is now a server to enforce and to run them. +[SQL](/basics/sql) possible: there is now a server to enforce and to run them. The tables are the same Lance tables either way. What changes is who resolves their names and who does the work. diff --git a/docs/web/basics/limits.mdx b/docs/web/basics/limits.mdx index 34c84f9ee..0c3647b03 100644 --- a/docs/web/basics/limits.mdx +++ b/docs/web/basics/limits.mdx @@ -94,7 +94,7 @@ not another. | `tableExists` / `namespaceExists` in TypeScript | not present | | Server-side jobs on a local database | run in-process; `events()` raises | -See [SDKs and SQL](/basics/apis) for why the first two hold. +See [SQL](/basics/sql) for why the first two hold. ## Nothing here is a quota {#not-quotas} diff --git a/docs/web/basics/query.mdx b/docs/web/basics/query.mdx index b643d0f35..449c9b498 100644 --- a/docs/web/basics/query.mdx +++ b/docs/web/basics/query.mdx @@ -72,7 +72,7 @@ query.cancel() # stop it for a job. -SQL requires a deployment. See [SDKs and SQL](/basics/apis). +SQL requires a deployment. See [SQL](/basics/sql#sql-is-remote). Query-builder searches -- vector, full-text, hybrid -- are ordinary calls that diff --git a/docs/web/basics/sdk.mdx b/docs/web/basics/sdk.mdx new file mode 100644 index 000000000..3f8170e11 --- /dev/null +++ b/docs/web/basics/sdk.mdx @@ -0,0 +1,99 @@ +--- +title: "SDKs" +sidebarTitle: "SDKs" +description: "The language clients — Python, TypeScript, Rust — and what stays true across all of them." +icon: code-compare +keywords: ["python", "typescript", "rust", "java", "sdk", "rest", "api reference"] +--- + +A language SDK is the primary way to work with LanceDB: create and manage +tables, write and query data, build indexes, run feature engineering. The same +table API works whether you're connected to an embedded database or an +Enterprise deployment -- application code moves between the two by changing +the connection URI. + +## Officially supported SDKs {#supported-sdks} + +Python, TypeScript and Rust are supported against both embedded and deployed +LanceDB. + +| Reference | Description | +|:--------------|-------------------| +| [Python](https://lancedb.github.io/lancedb/python/python/) | Full-featured Python client with pandas and numpy integration | +| [TypeScript](https://lancedb.github.io/lancedb/js/) | A TypeScript wrapper around the Rust library, built with `napi-rs` | +| [Rust](https://docs.rs/lancedb/latest/lancedb/index.html) | Native Rust library with persistent storage and high performance | + +Not every SDK covers the same surface, though: + +| | Python | TypeScript | +| --- | :---: | :---: | +| Create and manage catalog objects | yes | yes | +| Insert, merge, update, delete | yes | yes | +| Filter, project, aggregate, join | yes | yes | +| Vector search | yes | yes | +| Full-text search | yes | yes | +| Feature engineering, jobs | yes | partly | +| Runs against a local database | yes | yes | + +TypeScript has no methods for [functions](/management/function). Reach the +gap with SQL instead -- see [SQL](/basics/sql). + +## REST API {#rest} + +Enterprise A deployment implements the +[Lance REST Namespace](/basics/lance#enterprise), so the catalog is reachable +over HTTP by anything that speaks it -- see the +[REST API reference](/api-reference/rest). + +| Reference | Description | +|:--------------|-------------------| +| [Java](https://lancedb.github.io/lancedb/java/java/) | REST API Enterprise SDK in Java | + +## Community SDKs {#community-sdks} + +Contributed by the community rather than supported by LanceDB, so feature parity +and release cadence vary. + +| Reference | Description | +|:--------------|-------------------| +| [Go](https://pkg.go.dev/github.com/lancedb/lancedb-go/pkg/lancedb) | Community-contributed Go SDK | +| [Ruby](https://github.com/scientist-labs/lancelot) | Community-contributed Ruby bindings | +| [Swift](https://github.com/RyanLisse/LanceDbSwiftKit) | Community-contributed Swift SDK | +| [R](https://github.com/CathalByrneGit/lancedb) | Community-contributed R package | +| [Flutter](https://github.com/Alexcn/flutter_lancedb) | Community-contributed Flutter bindings | + +For any other language, [SQL](/basics/sql) reaches the same tables without a +LanceDB-specific SDK at all. + +## Python multiprocessing {#multiprocessing} + + +Do not use `fork` as the start method with Python's `multiprocessing` module. +Lance is multi-threaded internally, and `fork` with alive threads is unsafe -- +use `spawn` instead. See +[this discussion](https://discuss.python.org/t/concerns-regarding-deprecation-of-fork-with-alive-threads/33555) +for why. + + +## What stays the same {#invariants} + +Whichever you pick: + +- **Types are Arrow types.** A vector column is a `FixedSizeList` + everywhere, not a SQL type mapped onto storage. See + [Functions and types](/sql/functions). +- **Reads are Arrow.** Nothing is serialized into language objects on the way out + unless you convert it. +- **The catalog is one catalog.** A table created from TypeScript is visible to + Python and to SQL immediately -- there is no per-language namespace. + +## What to read next {#next} + + + + The same tables, reached by any Flight SQL client -- and the one way in for a language with no SDK. + + + Give a coding agent a current reference to this same API surface. + + diff --git a/docs/web/basics/sql.mdx b/docs/web/basics/sql.mdx new file mode 100644 index 000000000..5b8cff8b9 --- /dev/null +++ b/docs/web/basics/sql.mdx @@ -0,0 +1,119 @@ +--- +title: "SQL" +sidebarTitle: "SQL" +description: "The same tables, reached with SQL — the universal access path, and where every operation is formally documented." +icon: table-list +keywords: ["sql", "flight sql", "datafusion", "reference", "dialect"] +--- + +Enterprise SQL runs on a deployment. A local +database has no engine to plan a statement, so `execute_query` raises there. + +SQL is a second way to reach the same tables the [SDKs](/basics/sdk) do -- +not a different product, a different interface onto one engine. A table +written from Python is queried from SQL without an export step, and a table +created from SQL is visible to every SDK immediately. + +## Any language, via Flight SQL {#flight-sql} + +SQL is served over an +[Arrow Flight SQL](https://arrow.apache.org/docs/format/FlightSql.html) +endpoint, so any Flight SQL client reaches it -- which makes SQL the way in +for a language LanceDB has no SDK for. You don't need a LanceDB-specific +client at all, just a Flight SQL driver for your language. + +The TypeScript SDK itself has no SQL method, for the same reason a Go or C# +application would reach for SQL first: connect a Flight SQL client instead of +waiting on a native binding. See [SDKs](/basics/sdk) for the officially +supported and community clients, and reach for Flight SQL whenever yours +isn't among them. + +## Every SDK operation, in SQL {#sdk-parity} + +Broadly, a public SDK method has a corresponding SQL statement -- creating a +table is `CREATE TABLE`, inserting rows is `INSERT INTO`, building an index is +`CREATE INDEX`. The two describe the same operations, so whichever one your +code speaks, the other is available too. + +| | SDK | SQL | +| --- | :---: | :---: | +| Create and manage catalog objects | yes | partly | +| Insert, merge, update, delete | yes | yes | +| Filter, project, aggregate, join | yes | yes | +| Vector search | yes | -- | +| Full-text search | yes | yes | +| Feature engineering, jobs | yes | yes | +| Runs against a local database | yes | **no** | + +## Vector search has no SQL form {#no-vector-sql} + +The clearest exception to that parity. Similarity search is a query-builder +operation. A query that needs both vector similarity and SQL analytics runs +the search in an SDK and the analytics over its result. Full-text search *is* +available in SQL, as the [`fts()`](/sql/functions#fts) table function and the +[`contains_tokens`](/sql/scalar-functions#contains-tokens) predicate. + +The reverse gap also exists: a [view](/management/view) is a saved SQL query, +so SQL is the only way to create one -- there's nothing for an SDK method to +call. + +## SQL needs a deployment {#sql-is-remote} + +A connection to a directory or a bucket has no server to plan and execute a +statement, and asking it to raises `NotImplementedError`. This is the largest +behavioral difference between the embedded and deployed forms, and the reason +the SDKs are the portable choice: SDK code moves between the two by changing +the URI, SQL does not. + +```python +db = lancedb.connect("./.lancedb") # no SQL +db = lancedb.connect("db://my-database") # SQL +``` + +## Running SQL from Python {#sql-from-python} + +```python +reader = db.execute_query("SELECT id, text FROM my_docs LIMIT 10") +table = reader.read_all() +``` + +`execute_query` returns a blocking Arrow reader once results start arriving; it +does not wait for the whole query. `execute_query_async` returns a handle +instead -- see [Queries](/basics/query). + +## Choosing between them {#choosing} + +Reach for **the SDKs** when you are writing data, managing the catalog, running +vector search, or building an application that should work the same embedded and +deployed. + +Reach for **SQL** when the question is analytical -- joins across tables, +aggregates, window functions -- when the thing asking is a BI tool, a +notebook, or a person who already thinks in SQL, or when it's the only client +available for your language. + +The two compose. A common shape is SDK code to build and maintain tables, and +SQL for the analysis on top. + +## The complete reference {#reference} + +This page is the concept; [SQL Reference](/sql) is the specification. It has +one page per statement, syntax first -- and since every SDK operation has a +SQL form, those pages end up defining the precise behavior of the SDK +operations too, not just the SQL dialect. + + + DDL by object, then DML, then DQL -- the detailed technical documentation + that defines the behavior of every operation and SDK API. + + +## What to read next {#next} + + + + The language clients, and what stays true across all of them. + + + Give a coding agent a current reference to this same API surface. + + diff --git a/docs/web/curation/aggregate.mdx b/docs/web/curation/aggregate.mdx index fde064a99..91c32fdd4 100644 --- a/docs/web/curation/aggregate.mdx +++ b/docs/web/curation/aggregate.mdx @@ -7,7 +7,7 @@ keywords: ["aggregate", "group by", "class balance", "count", "profiling", "dist --- Enterprise Aggregation is SQL, and -[SQL needs a deployment](/basics/apis). +[SQL needs a deployment](/basics/sql#sql-is-remote). Before curating anything, find out what you have. Most of the surprises in a training set — a class that is 90% of the rows, a column that is half null, a diff --git a/docs/web/curation/index.mdx b/docs/web/curation/index.mdx index 09f7aa851..0bfc89b2d 100644 --- a/docs/web/curation/index.mdx +++ b/docs/web/curation/index.mdx @@ -16,7 +16,7 @@ reach for it, and links to the [SQL reference](/sql) for the complete syntax. Most curation is analytical -- grouping, joining, ranking -- which the query builders do not do. It is therefore SQL, and SQL needs a deployment. See -[SDKs and SQL](/basics/apis). +[SQL](/basics/sql#sql-is-remote). ## The four questions {#questions} diff --git a/docs/web/curation/join.mdx b/docs/web/curation/join.mdx index a05b93609..b4c198ef9 100644 --- a/docs/web/curation/join.mdx +++ b/docs/web/curation/join.mdx @@ -7,7 +7,7 @@ keywords: ["join", "labels", "metadata", "enrichment", "namespace"] --- Enterprise Joins are SQL, and -[SQL needs a deployment](/basics/apis). +[SQL needs a deployment](/basics/sql#sql-is-remote). Curation usually means combining things that were produced separately — images in one table, human labels in another, model scores in a third. A join is how diff --git a/docs/web/curation/windowing.mdx b/docs/web/curation/windowing.mdx index b8ad4aeca..fbb3cbbf2 100644 --- a/docs/web/curation/windowing.mdx +++ b/docs/web/curation/windowing.mdx @@ -7,7 +7,7 @@ keywords: ["window", "deduplication", "row_number", "rank", "train test split", --- Enterprise Window functions are SQL, and -[SQL needs a deployment](/basics/apis). +[SQL needs a deployment](/basics/sql#sql-is-remote). A window function computes across a set of related rows and returns a value **per row** — nothing is collapsed. That is what makes it the tool for "which of diff --git a/docs/web/docs.json b/docs/web/docs.json index a70073b54..308fdbf5a 100644 --- a/docs/web/docs.json +++ b/docs/web/docs.json @@ -230,6 +230,10 @@ { "source": "/troubleshooting", "destination": "/deployment/support" + }, + { + "source": "/basics/apis", + "destination": "/basics/sdk" } ], "navigation": { @@ -243,6 +247,8 @@ "index", "quickstart", "architecture", + "basics/sdk", + "basics/sql", "basics/agentic-skills" ] }, @@ -256,8 +262,7 @@ "basics/jobs", "tables/consistency", "basics/guarantees", - "basics/limits", - "basics/apis" + "basics/limits" ] }, { diff --git a/docs/web/management/database.mdx b/docs/web/management/database.mdx index 1c3e1c084..36c016e2e 100644 --- a/docs/web/management/database.mdx +++ b/docs/web/management/database.mdx @@ -40,7 +40,7 @@ storage and does the work itself. The third talks to a **deployment**. | --- | --- | --- | | Where queries run | in your process | on the server | | Table handle | `LanceTable` | `RemoteTable` | -| [SQL](/basics/apis) | -- | yes | +| [SQL](/basics/sql) | -- | yes | | Server-side [jobs](/basics/jobs) | -- | yes | | [Functions](/management/function) | -- | yes | | [Authorization](/governance/authorization) | storage permissions | granted per object | diff --git a/docs/web/management/index.mdx b/docs/web/management/index.mdx index 4e8bb85af..ce8ac9105 100644 --- a/docs/web/management/index.mdx +++ b/docs/web/management/index.mdx @@ -17,7 +17,7 @@ Operations that can take a while have an `_async` form returning a SQL requires a deployment -- a local database has no engine to plan a statement. -See [Python, TypeScript, and SQL](/basics/apis). +See [SQL](/basics/sql#sql-is-remote). ### Namespaces {#namespaces} diff --git a/docs/web/sql/data-types.mdx b/docs/web/sql/data-types.mdx index 10e432055..e46101a3e 100644 --- a/docs/web/sql/data-types.mdx +++ b/docs/web/sql/data-types.mdx @@ -75,7 +75,7 @@ SELECT id FROM documents WHERE vector IS NOT NULL Arithmetic over it is **list** arithmetic. There is no SQL similarity operator and no SQL form for vector search — run the search in an SDK and use SQL over -its result. See [SDKs and SQL](/basics/apis#no-vector-sql). +its result. See [SQL](/basics/sql#no-vector-sql). ### JSON {#json} diff --git a/docs/web/sql/index.mdx b/docs/web/sql/index.mdx index 7958ea63e..1057e9a0d 100644 --- a/docs/web/sql/index.mdx +++ b/docs/web/sql/index.mdx @@ -8,7 +8,7 @@ keywords: ["sql", "datafusion", "flight sql", "reference", "dialect"] Enterprise SQL runs on a deployment. A local database has no engine to plan a statement, so `execute_query` raises there -- see -[SDKs and SQL](/basics/apis). +[SQL](/basics/sql#sql-is-remote). This is a reference rather than a guide: one page per construct, syntax first. The guides elsewhere in these docs show the same operations from the SDKs.