Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 27 additions & 12 deletions docs/api-reference/index.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Client SDKs
title: SDKs and REST API Reference
sidebarTitle: "SDKs"
description: "SDK & REST API reference for LanceDB"
description: "SDK and REST API reference for LanceDB Enterprise and OSS."

---

Expand All @@ -15,20 +15,35 @@ If you're looking for conceptual and practical namespace guidance before diving

## Supported SDKs

Python, Typescript and Rust SDKs are officially supported by LanceDB.
Python, Typescript and Rust SDKs are officially supported by LanceDB. You can use these SDKs to interact with both LanceDB OSS and Enterprise deployments.

| SDK Reference | Description |
| Reference | Description |
|:--------------|-------------------|
| [Python SDK](https://lancedb.github.io/lancedb/python/python/) | Full-featured Python client with pandas & numpy integration |
| [Typescript SDK](https://lancedb.github.io/lancedb/js/) | A TypeScript wrapper around the Rust library, built with `napi-rs`
| [Rust SDK](https://docs.rs/lancedb/latest/lancedb/index.html) | Native Rust library with persistent-storage and high performance |
| <Icon icon="python" /> [Python](https://lancedb.github.io/lancedb/python/python/) | Full-featured Python client with pandas & numpy integration |
| <Icon icon="square-js" /> [Typescript](https://lancedb.github.io/lancedb/js/) | A TypeScript wrapper around the Rust library, built with `napi-rs`
| <Icon icon="rust" /> [Rust](https://docs.rs/lancedb/latest/lancedb/index.html) | Native Rust library with persistent-storage and high performance |

## Examples in other languages
## REST API SDKs

Other language SDKs are available through examples or third-party contributions.
<Badge color="red">Enterprise</Badge>

| SDK Examples | Description |
REST API-based SDKs provide a convenient way to interact with LanceDB Cloud and Enterprise deployments using the Lance REST Namespace API.

| Reference | Description |
|:--------------|-------------------|
| <Icon icon="java" /> [Java](https://lancedb.github.io/lancedb/java/java/)| REST API Enterprise SDK in Java |

## Community-driven SDKs

In addition to the officially supported SDKs, the LanceDB community may contribute SDKs in other languages.
These SDKs may not have the same level of support or feature parity as the official ones supported by LanceDB, but they can be an option
for users working in languages other than those listed above.

| Reference | Description |
|:--------------|-------------------|
| [Java API Quickstart]https://lancedb.github.io/lancedb/java/java/)| Streamline REST API interactions in Java|
| <Icon icon="golang" /> [Go](https://pkg.go.dev/github.com/lancedb/lancedb-go/pkg/lancedb) | Community-contributed Go SDK for LanceDB |
| <Icon icon="gem" /> [Ruby](https://github.com/scientist-labs/lancelot) | Community-contributed Ruby bindings for LanceDB |
| <Icon icon="swift" /> [Swift](https://github.com/RyanLisse/LanceDbSwiftKit) | Community-contributed Swift SDK for LanceDB |
| <Icon icon="R" /> [R](https://github.com/CathalByrneGit/lancedb) | Community-contributed R package for LanceDB |
| <Icon icon="flutter" /> [Flutter](https://github.com/Alexcn/flutter_lancedb) | Community-contributed Flutter bindings for LanceDB |

{/* TODO: Add Go bindings reference page here */}
107 changes: 68 additions & 39 deletions docs/namespaces.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,61 +23,90 @@ A namespace can contain a collection of tables, and it can also contain namespac

![](/static/assets/images/namespaces/lance-namespace.png)

## Root namespace and the familiar `data/` layout
Before diving into examples, it helps to keep two terms in mind: the **namespace client** is the abstraction that presents a consistent namespace API, while the **namespace implementation** is the concrete backend that resolves namespaces and table locations (for example, a local directory or an external catalog).
If you want to go deeper, see the Lance format [namespace documentation](https://lance.org/format/namespace/).

## Directory namespaces

The simplest namespace model in LanceDB is a single root namespace, often represented by one
directory:

```bash
/data/ # root namespace
├─ users.lance # table ["users"] in root
└─ orders.lance # table ["orders"] in root
./local_lancedb (root)
└── prod
└── search
└── user (table)
└── data (table)
```

As a user of LanceDB, you might never notice namespaces at first, because LanceDB exposes the single-level
hierarchy shown above, with the data stored in the `data/` directory, where the root namespace
is implicit. In alternative setups, you could have multiple namespaces that we won't cover here,
but you can learn more about them in the [namespace documentation](https://lance.org/format/namespace/) for the Lance format.
As a user of LanceDB OSS, you might never notice namespaces at first, because LanceDB exposes the single-level hierarchy shown above, with the data stored in the `data/` directory, where the root namespace is implicit. Connecting to this namespace is as simple as connecting to the catalog root:

## Best-practice guidance
```python Python icon="python"
import lancedb

- Use the default, single-level root namespace in LanceDB for locally stored, single-application, or early-stage projects.
- For remote storage locations, introduce explicit namespaces when multiple teams, environments, or domains share the same catalog.
- Treat namespace paths as stable identifiers (for example `"prod/search"`, `"staging/recs"`).
- Avoid hard-coding object-store table paths in application code -- instead, prefer catalog identifiers + namespaces.
# Connect to the directory namespace root
db = lancedb.connect("./local_lancedb")
```

See the Python example below for how to use namespaces in practice.
This will create the default namespace directory (`data/`) under the specified root path:

You can also explicitly connect to a namespace using `lancedb.connect_namespace(...)` with the directory namespace implementation:

```python Python icon="python"
import lancedb

# Local namespace-backed catalog root (DirectoryNamespace)
db = lancedb.connect_namespace("dir", {"root": "./namespace_test"})

# Business identifier + namespace path (stable app-level IDs)
namespace = ["prod", "recommendations"]
table_name = "user_profiles"

# Create namespace hierarchy sequentially
for i in range(1, len(namespace) + 1):
db.create_namespace(namespace[:i], mode="exist_ok")

# Good: resolve table through catalog + namespace
table = db.create_table(
table_name,
data=[{"id": 1, "vector": [0.1, 0.2], "name": "alice"}],
namespace=namespace,
mode="overwrite",
)
# See https://lance.org/format/namespace/dir/catalog-spec/
db = lancedb.connect_namespace("dir", {"root": "./local_lancedb"})

table_name = "user"
data = [{"id": 1, "vector": [0.1, 0.2], "name": "alice"}]

table = db.create_table(table_name, data=data, mode="create")
print(f"Created table: {table.name}")
# Created table: user
```

# Bad: Avoid hard-coded physical object-store table paths
# (it's bad for maintainability reasons)
# table = lancedb.connect(
# "s3://my-lakehouse/catalog/prod/recommendations/user_profiles.lance"
# )
<Info>
- For simple use cases in LanceDB OSS, you don't need to go too deep into namespaces.
- To integrate LanceDB with external catalogs and to use it as a true **multimodal lakehouse**, it's useful to understant the different namespace implementations and how to use them in your organization's setup.
</Info>

## Remote or external catalog namespaces

The example above showed local directory-baed namespaces. LanceDB also supports namespaces backed by remote object stores and external catalogs, via the REST namespace implementation.

For remote object stores with central metadata/catalog services (either commercial or open source), use the REST namespace implementation,
This is backed by REST routes
(for example `POST /v1/namespace/{id}/create` and `GET /v1/namespace/{id}/list`) and server-provided table locations.

For authentication, any property prefixed with `headers` is forwarded as an HTTP header
(for example `headers.Authorization` becomes `Authorization`, and `headers.X-API-Key` becomes `X-API-Key`).

```python Python icon="python"
import os
import lancedb

# Remote namespace-backed catalog root (RestNamespace)
# See https://lance.org/format/namespace/rest/catalog-spec/
db = lancedb.connect_namespace(
"rest",
{
"uri": "https://<your_catalog>.internal.<your_org>.com",
"headers.x-api-key": os.environ["API_KEY"],
# or:
# "headers.Authorization": f"Bearer {os.environ['REST_AUTH_TOKEN']}",
},
)
```
[LanceDB Enterprise](/enterprise) operates a REST namespace server on top of the Lance format, so any REST client that can speak the REST namespace API
contract can be used to interact with it. For authentication examples in LanceDB Enterprise, visit
the [Namespaces in SDKs](/tables/namespaces#namespaces-in-lancedb-enterprise) page.

## SDK usage
## Best practices

1. For language-specific examples of `namespace` usage across Python, TypeScript, and Rust, see "[Using namespaces in SDKs](/tables/namespaces)".
2. For REST-level operations, see the [REST API Reference](/api-reference/rest).
Below, we list some best practices for working with namespaces:
- For simple use cases and single, stand-alone applications, the directory-based root namespace is sufficient and requires no special configuration.
- For remote storage locations, introduce explicit namespaces when multiple teams, environments, or domains share the same catalog.
- Treat namespace paths as stable identifiers (for example `"prod/search"`, `"staging/recs"`).
- For maintainability reasons, avoid hard-coding object-store table paths in application code -- instead, prefer catalog identifiers + namespaces.
10 changes: 5 additions & 5 deletions docs/snippets/connection.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,23 @@ export const PyConnectObjectStorage = "import lancedb\n\nuri = \"s3://your-bucke

export const PyConnectObjectStorageAsync = "import lancedb\n\nuri = \"s3://your-bucket/path\"\n# You can also use \"gs://your-bucket/path\" or \"az://your-container/path\".\nasync_db = await lancedb.connect_async(uri)\n";

export const PyNamespaceAdminOps = "import lancedb\n\ndb = lancedb.connect_namespace(\"dir\", {\"root\": \"./data/sample-lancedb\"})\nnamespace = [\"prod\", \"search\"]\n\nfor i in range(1, len(namespace) + 1):\n db.create_namespace(namespace[:i], mode=\"exist_ok\")\n\nchild_namespaces = db.list_namespaces(namespace=[\"prod\"]).namespaces\nmetadata = db.describe_namespace([\"prod\", \"search\"])\n\ndb.drop_namespace([\"prod\", \"search\"], mode=\"skip\")\ndb.drop_namespace([\"prod\"], mode=\"skip\")\n";
export const PyNamespaceAdminOps = "import lancedb\n\ndb = lancedb.connect_namespace(\"dir\", {\"root\": \"./local_lancedb\"})\nnamespace = [\"prod\", \"search\"]\n\ndb.create_namespace([\"prod\"])\ndb.create_namespace([\"prod\", \"search\"])\n\nchild_namespaces = db.list_namespaces(namespace=[\"prod\"]).namespaces\nprint(f\"Child namespaces under {namespace}: {child_namespaces}\")\n# Child namespaces under ['prod', 'search']: ['search']\n\nmetadata = db.describe_namespace([\"prod\", \"search\"])\nprint(f\"Metadata for namespace {namespace}: {metadata}\")\n# Metadata for namespace ['prod', 'search']: properties=None\n\ndb.drop_namespace([\"prod\", \"search\"], mode=\"skip\")\ndb.drop_namespace([\"prod\"], mode=\"skip\")\n";

export const PyNamespaceTableOps = "import lancedb\n\ndb = lancedb.connect_namespace(\"dir\", {\"root\": \"./data/sample-lancedb\"})\nnamespace = [\"prod\", \"search\"]\n\nfor i in range(1, len(namespace) + 1):\n db.create_namespace(namespace[:i], mode=\"exist_ok\")\n\ndb.create_table(\n \"users\",\n data=[{\"id\": 1, \"vector\": [0.1, 0.2], \"name\": \"alice\"}],\n mode=\"overwrite\",\n namespace=namespace,\n)\n\ntable = db.open_table(\"users\", namespace=namespace)\ntables = db.list_tables(namespace=namespace).tables\n\ndb.drop_table(\"users\", namespace=namespace)\n# drop_all_tables is namespace-aware as well:\n# db.drop_all_tables(namespace=namespace)\n";
export const PyNamespaceTableOps = "import lancedb\n\ndb = lancedb.connect_namespace(\"dir\", {\"root\": \"./local_lancedb\"})\n\n# Create namespace tree: prod/search\ndb.create_namespace([\"prod\"], mode=\"exist_ok\")\ndb.create_namespace([\"prod\", \"search\"], mode=\"exist_ok\")\ndb.create_namespace([\"prod\", \"recommendations\"], mode=\"exist_ok\")\n\ndb.create_table(\n \"user\",\n data=[{\"id\": 1, \"vector\": [0.1, 0.2], \"name\": \"alice\"}],\n namespace=[\"prod\", \"search\"],\n mode=\"create\", # use \"overwrite\" only if you want to replace existing table\n)\n\ndb.create_table(\n \"user\",\n data=[{\"id\": 2, \"vector\": [0.3, 0.4], \"name\": \"bob\"}],\n namespace=[\"prod\", \"recommendations\"],\n mode=\"create\", # use \"overwrite\" only if you want to replace existing table\n)\n\n# Verify\nprint(db.list_namespaces()) # ['prod']\nprint(db.list_namespaces(namespace=[\"prod\"])) # ['recommendations', 'search']\nprint(db.list_tables(namespace=[\"prod\", \"search\"])) # ['user']\nprint(db.list_tables(namespace=[\"prod\", \"recommendations\"])) # ['user']\n";

export const TsConnect = "import * as lancedb from \"@lancedb/lancedb\";\n\nasync function connectExample(uri: string) {\n const db = await lancedb.connect(uri);\n return db;\n}\n";

export const TsConnectCloud = "const uri = \"db://your-database-uri\";\nconst apiKey = \"your-api-key\";\nconst region = \"us-east-1\";\n";

export const TsConnectObjectStorage = "async function connectObjectStorageExample() {\n const uri = \"s3://your-bucket/path\";\n // You can also use \"gs://your-bucket/path\" or \"az://your-container/path\".\n const db = await lancedb.connect(uri);\n return db;\n}\n";

export const TsNamespaceTableOps = "const db = await lancedb.connect(uri);\nconst namespace = [\"prod\", \"search\"];\n\nawait db.createTable(\n \"users\",\n [{ id: 1, name: \"alice\" }],\n namespace,\n { mode: \"overwrite\" },\n);\n\nconst table = await db.openTable(\"users\", namespace);\nconst tableNames = await db.tableNames(namespace);\n\nawait db.dropTable(\"users\", namespace);\n// dropAllTables is namespace-aware as well:\n// await db.dropAllTables(namespace);\n";

export const RsConnect = "async fn connect_example(uri: &str) {\n let db = connect(uri).execute().await.unwrap();\n let _ = db;\n}\n";

export const RsConnectCloud = "let uri = \"db://your-database-uri\";\nlet api_key = \"your-api-key\";\nlet region = \"us-east-1\";\n";

export const RsConnectObjectStorage = "let uri = \"s3://your-bucket/path\";\n// You can also use \"gs://your-bucket/path\" or \"az://your-container/path\".\n";

export const RsNamespaceTableOps = "let conn = connect(uri).execute().await?;\nlet namespace = vec![\"prod\".to_string(), \"search\".to_string()];\n\nlet schema = std::sync::Arc::new(arrow_schema::Schema::new(vec![\n arrow_schema::Field::new(\"id\", arrow_schema::DataType::Int64, false),\n]));\n\nconn.create_empty_table(\"users\", schema)\n .namespace(namespace.clone())\n .execute()\n .await?;\n\nlet _table = conn\n .open_table(\"users\")\n .namespace(namespace.clone())\n .execute()\n .await?;\nlet _table_names = conn\n .table_names()\n .namespace(namespace.clone())\n .execute()\n .await?;\n\nconn.drop_table(\"users\", &namespace).await?;\n// drop_all_tables is namespace-aware as well:\n// conn.drop_all_tables(&namespace).await?;\n";
export const RsNamespaceAdminOps = "let mut properties = std::collections::HashMap::new();\nproperties.insert(\"root\".to_string(), \"./local_lancedb\".to_string());\nlet db = lancedb::connect_namespace(\"dir\", properties).execute().await?;\nlet namespace = vec![\"prod\".to_string(), \"search\".to_string()];\n\ndb.create_namespace(lancedb::database::CreateNamespaceRequest {\n namespace: vec![\"prod\".to_string()],\n})\n.await?;\ndb.create_namespace(lancedb::database::CreateNamespaceRequest {\n namespace: namespace.clone(),\n})\n.await?;\n\nlet child_namespaces = db\n .list_namespaces(lancedb::database::ListNamespacesRequest {\n namespace: vec![\"prod\".to_string()],\n ..Default::default()\n })\n .await?;\nprintln!(\n \"Child namespaces under {:?}: {:?}\",\n namespace, child_namespaces\n);\n// Child namespaces under [\"prod\", \"search\"]: [\"search\"]\n\ndb.drop_namespace(lancedb::database::DropNamespaceRequest {\n namespace: namespace.clone(),\n})\n.await?;\ndb.drop_namespace(lancedb::database::DropNamespaceRequest {\n namespace: vec![\"prod\".to_string()],\n})\n.await?;\n";

export const RsNamespaceTableOps = "let conn = connect(uri).execute().await?;\nlet search_namespace = vec![\"prod\".to_string(), \"search\".to_string()];\nlet recommendations_namespace = vec![\"prod\".to_string(), \"recommendations\".to_string()];\n\nlet schema = std::sync::Arc::new(arrow_schema::Schema::new(vec![\n arrow_schema::Field::new(\"id\", arrow_schema::DataType::Int64, false),\n]));\n\nconn.create_empty_table(\"user\", schema.clone())\n .namespace(search_namespace.clone())\n .execute()\n .await?;\n\nconn.create_empty_table(\"user\", schema)\n .namespace(recommendations_namespace.clone())\n .execute()\n .await?;\n\nlet search_table_names = conn\n .table_names()\n .namespace(search_namespace)\n .execute()\n .await?;\nlet recommendation_table_names = conn\n .table_names()\n .namespace(recommendations_namespace)\n .execute()\n .await?;\n\nprintln!(\"{search_table_names:?}\"); // [\"user\"]\nprintln!(\"{recommendation_table_names:?}\"); // [\"user\"]\n";

2 changes: 1 addition & 1 deletion docs/snippets/multimodal.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{/* Auto-generated by scripts/mdx_snippets_gen.py. Do not edit manually. */}

export const PyBlobApiIngest = "import lancedb\nimport lance\n\ndb = lancedb.connect(db_path_factory(\"blob_db\"))\n \n# Create sample data\ndata = [\n {\"id\": 1, \"video\": b\"fake_video_bytes_1\"},\n {\"id\": 2, \"video\": b\"fake_video_bytes_2\"}\n]\n \n# Create the table\ntbl = db.create_table(\"videos\", data=data, schema=schema)\n";
export const PyBlobApiIngest = "import lancedb\n\ndb = lancedb.connect(db_path_factory(\"blob_db\"))\n \n# Create sample data\ndata = [\n {\"id\": 1, \"video\": b\"fake_video_bytes_1\"},\n {\"id\": 2, \"video\": b\"fake_video_bytes_2\"}\n]\n \n# Create the table\ntbl = db.create_table(\"videos\", data=data, schema=schema)\n";

export const PyBlobApiSchema = "import pyarrow as pa\n\n# Define schema with Blob API metadata for lazy loading\nschema = pa.schema([\n pa.field(\"id\", pa.int64()),\n pa.field(\n \"video\", \n pa.large_binary(), \n metadata={\"lance-encoding:blob\": \"true\"} # Enable Blob API\n ),\n])\n";

Expand Down
Loading
Loading