mirror of
https://github.com/lancedb/lancedb.git
synced 2026-10-13 15:22:30 +00:00
Move the public website pages into `docs/web` beside the SDK, with
shared navigation and executable example sources in `docs/web-tests`.
The combined website is assembled by
[lancedb/docs#355](https://github.com/lancedb/docs/pull/355), with six
Enterprise replacements from
[lancedb/sophon#7681](https://github.com/lancedb/sophon/pull/7681).
This includes Function guidance, runnable Quickstarts, regenerated
snippets, production contact/demo fixes, the legacy SQL route, and the
LeRobot redirect. LeRobot remains attributed to Geneva; all 34 Geneva
pages remain in the docs repository until Function officially launches.
Materialized-view guidance follows the full rebuild refresh introduced
by #4373: local refresh writes the complete result, has no `full`
argument, supports `source_version`, and no longer requires stable row
IDs. Deployment SQL refresh options and stable-ID setup are qualified by
version/configuration. Function input guidance distinguishes ordinary
stored columns from computed inputs supported by newer deployments.
**Validation:** independently accepted local checks include 95 Python
tests (real Enterprise excluded), eight TypeScript tests, Rust
Quickstart, snippet parity, typos, deterministic assembly, Mint
validation and links/anchors/redirects. The combined baseline retains
all 181 production routes and 17 legacy redirects. Examples ran locally
against source-built Python SDK 0.40.0b13; existing GitHub workflows do
not run `docs/web-tests`. New main at `069b2f7d` is 0.41.0b0 and adds
computed Function inputs; that SDK was not exercised by the accepted
tests. Latest prose corrections receive focused site validation.
**Merge/rollout:** merge this and #7681 before #355's combined CI, which
reads producer `main`. This is migration infrastructure: section
overlays, source-owned skills and automatic versioned paired releases
remain follow-ups. The current manual publisher is transitional. Hosted
validation, a supported SDK/Enterprise release pair and a real
Enterprise walkthrough remain pending.
Production Mintlify watches `lancedb/docs:deploy-freeze`, directory
`docs`; preserve that source through review. The separate SDK GitHub
Pages reference workflow rebuilds on main merges.
**Updated-head CI (9a50f8db):**
[Typos](https://github.com/lancedb/lancedb/actions/runs/37654185443/job/112904990558),
[PR
title](https://github.com/lancedb/lancedb/actions/runs/37654179507/job/112904974595)
and
[Aikido](https://app.aikido.dev/featurebranch/scan/215386145?groupId=74229)
pass. Critical findings in the example lockfiles were patched: all Sharp
copies use 0.35.5, protobufjs 7.6.6, tar 7.5.22, quinn-proto 0.11.19,
zerovec 0.11.8 and zerovec-derive 0.11.6. The SDK's product dependencies
are unchanged. The revised lockfiles pass eight TypeScript examples,
HuggingFace decode/resize/crop/rescale/normalize plus AVIF roundtrip,
and Rust Quickstart. Aikido passing does not mean every advisory is
cleared; npm still reports 29 high and five moderate advisories in the
example dependency graph. No scanner bypass or suppression was added.
The Function prose correction passes combined/standalone Mint,
deterministic assembly, routes and assets. The revised 325-file site
checksum is
`175bec06864abb400dd292e667ba93448c0479b8359fd7bf6146afabf9040647`. This
PR remains open for independent review; further merges are on hold.
---------
Co-authored-by: Brendan Clement <brendan.clement@lancedb.com>
348 lines
12 KiB
Plaintext
348 lines
12 KiB
Plaintext
---
|
|
title: "Creating a table"
|
|
sidebarTitle: "Create Table"
|
|
description: "Start here: turn the data you already have into a LanceDB table."
|
|
icon: table
|
|
keywords: ["create table", "ingest", "arrow", "pandas", "polars", "pydantic", "schema"]
|
|
---
|
|
|
|
import {
|
|
TsConnect,
|
|
RsConnect,
|
|
} from '/snippets/connection.mdx';
|
|
import {
|
|
PyCreateTableFromDicts as CreateTableFromDicts,
|
|
TsCreateTableFromDicts as TsCreateTableFromDicts,
|
|
RsCreateTableFromDicts as RsCreateTableFromDicts,
|
|
PyCreateTableConflictHandling as CreateTableConflictHandling,
|
|
TsCreateTableConflictHandling as TsCreateTableConflictHandling,
|
|
RsCreateTableConflictHandling as RsCreateTableConflictHandling,
|
|
PyCreateTableFromPandas as CreateTableFromPandas,
|
|
PyCreateTableCustomSchema as CreateTableCustomSchema,
|
|
TsCreateTableCustomSchema as TsCreateTableCustomSchema,
|
|
RsCreateTableCustomSchema as RsCreateTableCustomSchema,
|
|
PyCreateTableFromPolars as CreateTableFromPolars,
|
|
PyCreateTableFromArrow as CreateTableFromArrow,
|
|
TsCreateTableFromArrow as TsCreateTableFromArrow,
|
|
RsCreateTableFromArrow as RsCreateTableFromArrow,
|
|
PyCreateTableFromPydantic as CreateTableFromPydantic,
|
|
PyCreateTableNestedSchema as CreateTableNestedSchema,
|
|
PyOpenExistingTable as OpenExistingTable,
|
|
TsOpenExistingTable as TsOpenExistingTable,
|
|
RsOpenExistingTable as RsOpenExistingTable,
|
|
PyCreateEmptyTable as CreateEmptyTable,
|
|
TsCreateEmptyTable as TsCreateEmptyTable,
|
|
RsCreateEmptyTable as RsCreateEmptyTable,
|
|
PyCreateEmptyTablePydantic as CreateEmptyTablePydantic,
|
|
PyDropTable as DropTable,
|
|
TsDropTable as TsDropTable,
|
|
RsDropTable as RsDropTable,
|
|
PyTablesBasicConnect as TablesBasicConnect,
|
|
PyTablesDocumentModel as TablesDocumentModel,
|
|
PyTablesTzValidator as TablesTzValidator,
|
|
} from '/snippets/tables.mdx';
|
|
|
|
A table is created from data you already have -- a list of objects, an Arrow
|
|
table, a pandas or polars frame, Pydantic models -- or from a schema alone when
|
|
the rows come later.
|
|
|
|
## Create a table with data {#create-a-table-with-data}
|
|
|
|
Initialize a LanceDB connection and create a table
|
|
|
|
<CodeGroup>
|
|
<CodeBlock filename="Python" language="Python" icon="python">
|
|
{TablesBasicConnect}
|
|
</CodeBlock>
|
|
|
|
<CodeBlock filename="TypeScript" language="TypeScript" icon="square-js">
|
|
{TsConnect}
|
|
</CodeBlock>
|
|
|
|
<CodeBlock filename="Rust" language="Rust" icon="rust">
|
|
{RsConnect}
|
|
</CodeBlock>
|
|
</CodeGroup>
|
|
|
|
Depending on the SDK, LanceDB can ingest arrays of records, Arrow tables or record batches, and Arrow batch iterators or readers. Let's take a look at some of the common patterns.
|
|
|
|
### From list of objects {#from-list-of-objects}
|
|
|
|
You can provide a list of objects to create a table. The Python and TypeScript SDKs
|
|
support lists/arrays of dictionaries, while the Rust SDK supports lists of structs.
|
|
In Python, pass a list or other batch-like object; a single bare `dict` or single
|
|
`LanceModel` is rejected.
|
|
|
|
<CodeGroup>
|
|
<CodeBlock filename="Python" language="Python" icon="python">
|
|
{CreateTableFromDicts}
|
|
</CodeBlock>
|
|
|
|
<CodeBlock filename="TypeScript" language="TypeScript" icon="square-js">
|
|
{TsCreateTableFromDicts}
|
|
</CodeBlock>
|
|
|
|
<CodeBlock filename="Rust" language="Rust" icon="rust">
|
|
{RsCreateTableFromDicts}
|
|
</CodeBlock>
|
|
</CodeGroup>
|
|
|
|
### Handle existing tables {#handle-existing-tables}
|
|
|
|
By default, `create_table` raises an error if a table with the same name already exists.
|
|
You can change this behavior with two parameters that resolve the conflict in different ways:
|
|
|
|
- **Idempotent open**: return the existing table without modifying it. Use when your
|
|
code may run more than once (notebooks, retries, init scripts) and you want to reuse
|
|
the table on subsequent runs. The provided data is ignored, but the schema is
|
|
validated against the existing table and a mismatch raises an error.
|
|
- **Overwrite**: drop the existing table and create a new one with the provided data.
|
|
Use this for test fixtures or when you intentionally want to replace prior contents.
|
|
This permanently discards the old table's data.
|
|
|
|
<CodeGroup>
|
|
<CodeBlock filename="Python" language="Python" icon="python">
|
|
{CreateTableConflictHandling}
|
|
</CodeBlock>
|
|
|
|
<CodeBlock filename="TypeScript" language="TypeScript" icon="square-js">
|
|
{TsCreateTableConflictHandling}
|
|
</CodeBlock>
|
|
|
|
<CodeBlock filename="Rust" language="Rust" icon="rust">
|
|
{RsCreateTableConflictHandling}
|
|
</CodeBlock>
|
|
</CodeGroup>
|
|
|
|
<Note>
|
|
`exist_ok` / `existOk` does not append the provided data to an existing table. Use
|
|
[`table.add()`](/ingestion/insert) for that. If you need to ensure a table exists *and*
|
|
contains specific rows, prefer the [empty-table-then-add pattern](#create-empty-table).
|
|
</Note>
|
|
|
|
### From a custom schema {#from-a-custom-schema}
|
|
|
|
You can define a custom Arrow schema for the table. This is useful when you want to have more control over the column types and metadata.
|
|
|
|
<CodeGroup>
|
|
<CodeBlock filename="Python" language="Python" icon="python">
|
|
{CreateTableCustomSchema}
|
|
</CodeBlock>
|
|
|
|
<CodeBlock filename="TypeScript" language="TypeScript" icon="square-js">
|
|
{TsCreateTableCustomSchema}
|
|
</CodeBlock>
|
|
|
|
<CodeBlock filename="Rust" language="Rust" icon="rust">
|
|
{RsCreateTableCustomSchema}
|
|
</CodeBlock>
|
|
</CodeGroup>
|
|
|
|
An explicit schema is also where you control nullability. If later writes omit a
|
|
non-nullable column, or provide actual nulls for it, ingestion fails; nullable columns can be
|
|
omitted or written with null values. Without an explicit schema, Python infers list-like vector
|
|
values as fixed-size `float32` vector fields from the observed dimension.
|
|
|
|
For Python ingest, malformed vector values fail by default. If you expect occasional wrong-length,
|
|
null, or NaN vectors, choose an `on_bad_vectors` policy: `"drop"` removes those rows, `"fill"` writes
|
|
`fill_value`, and `"null"` writes nulls.
|
|
|
|
### From an Arrow Table {#from-an-arrow-table}
|
|
You can also create LanceDB tables directly from Arrow tables.
|
|
Rust uses an Arrow `RecordBatchReader` for the same Arrow-native ingest flow.
|
|
|
|
<CodeGroup>
|
|
<CodeBlock filename="Python" language="Python" icon="python">
|
|
{CreateTableFromArrow}
|
|
</CodeBlock>
|
|
|
|
<CodeBlock filename="TypeScript" language="TypeScript" icon="square-js">
|
|
{TsCreateTableFromArrow}
|
|
</CodeBlock>
|
|
|
|
<CodeBlock filename="Rust" language="Rust" icon="rust">
|
|
{RsCreateTableFromArrow}
|
|
</CodeBlock>
|
|
</CodeGroup>
|
|
|
|
|
|
### From a Pandas DataFrame {#from-a-pandas-dataframe}
|
|
<Badge color="green">Python Only</Badge>
|
|
|
|
<CodeGroup>
|
|
<CodeBlock filename="Python" language="Python" icon="python">
|
|
{CreateTableFromPandas}
|
|
</CodeBlock>
|
|
</CodeGroup>
|
|
|
|
<Note title="Note">
|
|
Data is converted to Arrow before being written to disk. For maximum control over how data is saved, either provide the PyArrow schema to convert to or else provide a PyArrow Table directly.
|
|
</Note>
|
|
|
|
<Note title="Vector Column Type">
|
|
The **`vector`** column needs to be a [Vector](/integrations/data/pydantic#vector-field) (defined as [pyarrow.FixedSizeList](https://arrow.apache.org/docs/python/generated/pyarrow.list_.html)) type.
|
|
</Note>
|
|
|
|
### From a Polars DataFrame {#from-a-polars-dataframe}
|
|
<Badge color="green">Python Only</Badge>
|
|
|
|
LanceDB supports [Polars](https://pola.rs/), a modern, fast DataFrame library
|
|
written in Rust. Just like in Pandas, the Polars integration is enabled by PyArrow
|
|
under the hood. A deeper integration between LanceDB Tables and Polars DataFrames
|
|
is on the way.
|
|
|
|
<CodeGroup>
|
|
<CodeBlock filename="Python" language="Python" icon="python">
|
|
{CreateTableFromPolars}
|
|
</CodeBlock>
|
|
</CodeGroup>
|
|
|
|
### From Pydantic Models {#from-pydantic-models}
|
|
<Badge color="green">Python Only</Badge>
|
|
|
|
When you create an empty table without data, you must specify the table schema.
|
|
LanceDB supports creating tables by specifying a PyArrow schema or a specialized
|
|
Pydantic model called `LanceModel`.
|
|
|
|
For example, the following Content model specifies a table with 5 columns:
|
|
`movie_id`, `vector`, `genres`, `title`, and `imdb_id`. When you create a table, you can
|
|
pass the class as the value of the `schema` parameter to `create_table`.
|
|
The `vector` column is a `Vector` type, which is a specialized Pydantic type that
|
|
can be configured with the vector dimensions. It is also important to note that
|
|
LanceDB only understands subclasses of `lancedb.pydantic.LanceModel`
|
|
(which itself derives from `pydantic.BaseModel`).
|
|
|
|
<CodeGroup>
|
|
<CodeBlock filename="Python" language="Python" icon="python">
|
|
{CreateTableFromPydantic}
|
|
</CodeBlock>
|
|
</CodeGroup>
|
|
|
|
#### Nested schemas {#nested-schemas}
|
|
|
|
Sometimes your data model may contain nested objects. For example, you may want to store the document string and the document source name as a nested Document object:
|
|
|
|
<CodeGroup>
|
|
<CodeBlock filename="Python" language="Python" icon="python">
|
|
{TablesDocumentModel}
|
|
</CodeBlock>
|
|
</CodeGroup>
|
|
|
|
This can be used as the type of a LanceDB table column:
|
|
|
|
<CodeGroup>
|
|
<CodeBlock filename="Python" language="Python" icon="python">
|
|
{CreateTableNestedSchema}
|
|
</CodeBlock>
|
|
</CodeGroup>
|
|
|
|
This creates a struct column called "document" that has two subfields
|
|
called "content" and "source":
|
|
|
|
```bash
|
|
In [28]: tbl.schema
|
|
Out[28]:
|
|
id: string not null
|
|
vector: fixed_size_list<item: float>[1536] not null
|
|
child 0, item: float
|
|
document: struct<content: string not null, source: string not null> not null
|
|
child 0, content: string not null
|
|
child 1, source: string not null
|
|
```
|
|
|
|
#### Validators {#validators}
|
|
|
|
Because `LanceModel` inherits from Pydantic's `BaseModel`, you can combine them with Pydantic's
|
|
[field validators](https://docs.pydantic.dev/latest/concepts/validators). The example
|
|
below shows how to add a validator to ensure that only valid timezone-aware datetime objects are used
|
|
for a `created_at` field.
|
|
|
|
<CodeGroup>
|
|
<CodeBlock filename="Python" language="Python" icon="python">
|
|
{TablesTzValidator}
|
|
</CodeBlock>
|
|
</CodeGroup>
|
|
|
|
When you run this code it, should raise the `ValidationError`.
|
|
|
|
<Note>
|
|
Datasets too large to pass to `create_table` at once are covered separately --
|
|
see [Insert data](/ingestion/insert#large-datasets), which explains why
|
|
`table.add()` parallelizes where `create_table` does not.
|
|
</Note>
|
|
|
|
## Create empty table {#create-empty-table}
|
|
You can create an empty table for scenarios where you want to add data to the table later.
|
|
An example would be when you want to collect data from a stream/external file and then add it to a table in
|
|
batches.
|
|
|
|
An empty table can be initialized via an Arrow schema.
|
|
|
|
<CodeGroup>
|
|
<CodeBlock filename="Python" language="Python" icon="python">
|
|
{CreateEmptyTable}
|
|
</CodeBlock>
|
|
|
|
<CodeBlock filename="TypeScript" language="TypeScript" icon="square-js">
|
|
{TsCreateEmptyTable}
|
|
</CodeBlock>
|
|
|
|
<CodeBlock filename="Rust" language="Rust" icon="rust">
|
|
{RsCreateEmptyTable}
|
|
</CodeBlock>
|
|
</CodeGroup>
|
|
|
|
Alternatively, you can also use Pydantic to specify the schema for the empty table. Note that we do not
|
|
directly import `pydantic` but instead use `lancedb.pydantic` which is a subclass of `pydantic.BaseModel`
|
|
that has been extended to support LanceDB specific types like `Vector`.
|
|
|
|
<CodeGroup>
|
|
<CodeBlock filename="Python" language="Python" icon="python">
|
|
{CreateEmptyTablePydantic}
|
|
</CodeBlock>
|
|
</CodeGroup>
|
|
|
|
Once the empty table has been created, you can append to it or modify its contents,
|
|
as explained in [Ingesting data](/ingestion).
|
|
|
|
## Open an existing table {#open-an-existing-table}
|
|
|
|
You can open an existing table by specifying the name of the table to the `open_table` / `openTable` method.
|
|
If you forget the name of your table, you can always get a listing of all table names.
|
|
|
|
<CodeGroup>
|
|
<CodeBlock filename="Python" language="Python" icon="python">
|
|
{OpenExistingTable}
|
|
</CodeBlock>
|
|
|
|
<CodeBlock filename="TypeScript" language="TypeScript" icon="square-js">
|
|
{TsOpenExistingTable}
|
|
</CodeBlock>
|
|
|
|
<CodeBlock filename="Rust" language="Rust" icon="rust">
|
|
{RsOpenExistingTable}
|
|
</CodeBlock>
|
|
</CodeGroup>
|
|
|
|
## Drop a table {#drop-a-table}
|
|
|
|
Use the `drop_table()` method on the database to remove a table.
|
|
|
|
<CodeGroup>
|
|
<CodeBlock filename="Python" language="Python" icon="python">
|
|
{DropTable}
|
|
</CodeBlock>
|
|
|
|
<CodeBlock filename="TypeScript" language="TypeScript" icon="square-js">
|
|
{TsDropTable}
|
|
</CodeBlock>
|
|
|
|
<CodeBlock filename="Rust" language="Rust" icon="rust">
|
|
{RsDropTable}
|
|
</CodeBlock>
|
|
</CodeGroup>
|
|
|
|
This permanently removes the table and is not recoverable, unlike deleting rows.
|
|
By default, if the table does not exist an exception is raised. To suppress this,
|
|
you can pass in `ignore_missing=True`.
|