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
4 changes: 3 additions & 1 deletion docs/api-reference/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ refer to the API documentation linked below.

If you're looking for a REST API reference, visit the [REST API](/api-reference/rest) page.

If you're looking for conceptual and practical namespace guidance before diving into method signatures, see
[Namespaces and Catalog Model](/namespaces) and [Using Namespaces in SDKs](/tables/namespaces).

## Supported SDKs

Python, Typescript and Rust SDKs are officially supported by LanceDB.
Expand All @@ -29,4 +32,3 @@ Other language SDKs are available through examples or third-party contributions.
| [Java API Quickstart]https://lancedb.github.io/lancedb/java/java/)| Streamline REST API interactions in Java|

{/* TODO: Add Go bindings reference page here */}

5 changes: 3 additions & 2 deletions docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"pages": [
"index",
"lance",
"features"
"namespaces"
]
},
{
Expand Down Expand Up @@ -80,6 +80,7 @@
"tables/multimodal",
"tables/schema",
"tables/update",
"tables/namespaces",
"tables/versioning",
"tables/consistency"
]
Expand Down Expand Up @@ -383,4 +384,4 @@
"destination": "tutorials/search/:slug*"
}
]
}
}
99 changes: 0 additions & 99 deletions docs/features.mdx

This file was deleted.

74 changes: 74 additions & 0 deletions docs/namespaces.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
title: "Namespaces and the Catalog Model"
sidebarTitle: "Namespaces"
description: "Understand LanceDB as a catalog-level abstraction over Lance's table format, and learn how namespaces help organize Lance tables."
icon: "sitemap"
keywords: ["namespace", "catalog", "lance format", "table format", "lancedb"]
---

Despite its name, LanceDB is not a "database" in the traditional sense -- it is a **Multimodal Lakehouse** that builds on the table abstraction,
similar to many other lakehouse projects. LanceDB exposes a catalog-level abstraction over the Lance table format, via a *namespace spec*.

Lance provides the **file** and **table** formats to store and manage your data and indexes.
LanceDB operates at the catalog layer (used to organize, discover, and operate on many Lance tables)
and provides a compute engine on top of the Lance format.

This is why many SDK methods in LanceDB, like `create_table`, `open_table`, `drop_table`, and
`rename_table`, accept a `namespace` parameter as input.

## Namespace hierarchy

Namespaces are generalizations of catalog specs that give platform developers a clean way to present Lance tables in the structures users expect. The diagram below shows how the hierarchy can go beyond a single level.
A namespace can contain a collection of tables, and it can also contain namespaces recursively.

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

## Root namespace and the familiar `data/` layout

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
```

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

## Best-practice guidance

- Use the default, single-level root namespace in LanceDB for locally stored, single applications 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.

See the Python example below for how to use namespaces in practice.

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

# App config: only the catalog endpoint/root is configured once.
db = lancedb.connect("s3://my-lakehouse/catalog")

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

# Good: resolve table through catalog + namespace
table = db.open_table(table_name, namespace=namespace)

# 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"
# )
```

## SDK usage

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).
8 changes: 8 additions & 0 deletions docs/snippets/connection.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +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(\"./data/sample-lancedb\")\ndb.create_namespace([\"prod\"])\ndb.create_namespace([\"prod\", \"search\"])\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 PyNamespaceTableOps = "import lancedb\n\ndb = lancedb.connect(\"./data/sample-lancedb\")\nnamespace = [\"prod\", \"search\"]\n\ndb.create_table(\n \"users\",\n data=[{\"id\": 1, \"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 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";

5 changes: 3 additions & 2 deletions docs/snippets/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ export const PyQuickstartVectorSearch1Async = "# Let's search for vectors simila

export const PyQuickstartVectorSearch2 = "# Let's search for vectors similar to \"wizard\"\nquery_vector = [0.7, 0.3, 0.5]\n\nresults = table.search(query_vector).limit(2).to_polars()\nprint(results)\n";

export const TsQuickstartOutputPandas = "result = await table.search(queryVector).limit(2).toArray();\n";

export const TsQuickstartAddData = "const moreData = [\n { id: \"7\", text: \"mage\", vector: [0.6, 0.3, 0.4] },\n { id: \"8\", text: \"bard\", vector: [0.3, 0.8, 0.4] },\n];\n\n// Add data to table\nawait table.add(moreData);\n";

export const TsQuickstartCreateTable = "const data = [\n { id: \"1\", text: \"knight\", vector: [0.9, 0.4, 0.8] },\n { id: \"2\", text: \"ranger\", vector: [0.8, 0.4, 0.7] },\n { id: \"9\", text: \"priest\", vector: [0.6, 0.2, 0.6] },\n { id: \"4\", text: \"rogue\", vector: [0.7, 0.4, 0.7] },\n];\nlet table = await db.createTable(\"adventurers\", data, { mode: \"overwrite\" });\n";
Expand All @@ -30,6 +28,8 @@ export const TsQuickstartOpenTable = "table = await db.openTable(\"adventurers\"

export const TsQuickstartOutputArray = "result = await table.search(queryVector).limit(2).toArray();\nconsole.table(result);\n";

export const TsQuickstartOutputPandas = "result = await table.search(queryVector).limit(2).toArray();\n";

export const TsQuickstartVectorSearch1 = "// Let's search for vectors similar to \"warrior\"\nlet queryVector = [0.8, 0.3, 0.8];\n\nlet result = await table.search(queryVector).limit(2).toArray();\nconsole.table(result);\n";

export const TsQuickstartVectorSearch2 = "// Let's search for vectors similar to \"wizard\"\nqueryVector = [0.7, 0.3, 0.5];\n\nconst results = await table.search(queryVector).limit(2).toArray();\nconsole.table(results);\n";
Expand All @@ -49,3 +49,4 @@ export const RsQuickstartOutputArray = "let result: DataFrame = table\n .quer
export const RsQuickstartVectorSearch1 = "// Let's search for vectors similar to \"warrior\"\nlet query_vector = [0.8, 0.3, 0.8];\n\nlet result: DataFrame = table\n .query()\n .nearest_to(&query_vector)\n .unwrap()\n .limit(2)\n .select(Select::Columns(vec![\"text\".to_string()]))\n .execute()\n .await\n .unwrap()\n .into_polars()\n .await\n .unwrap();\nprintln!(\"{result:?}\");\n";

export const RsQuickstartVectorSearch2 = "// Let's search for vectors similar to \"wizard\"\nlet query_vector = [0.7, 0.3, 0.5];\n\nlet result: DataFrame = table\n .query()\n .nearest_to(&query_vector)\n .unwrap()\n .limit(2)\n .select(Select::Columns(vec![\"text\".to_string()]))\n .execute()\n .await\n .unwrap()\n .into_polars()\n .await\n .unwrap();\nprintln!(\"{result:?}\");\nlet text_col = result.column(\"text\").unwrap().str().unwrap();\nlet top_two = vec![\n text_col.get(0).unwrap().to_string(),\n text_col.get(1).unwrap().to_string(),\n];\n";

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading