> ## Documentation Index
> Fetch the complete documentation index at: https://lancedb-bcbb4faf-weston-feat-streaming-dataset.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Get started with LanceDB in minutes.

export const TsQuickstartVectorSearch1 = "// Search for examples similar to a \"wise magical advisor\"\nlet queryVector = [0.2, 0.8, 0.4, 0.9];\n\nlet result = await table\n  .search(queryVector)\n  .select([\"name\", \"role\", \"description\", \"_distance\"])\n  .limit(2)\n  .toArray();\nconsole.table(result);\n";

export const TsQuickstartQueryFeature = "const features = await table\n  .query()\n  .select([\"name\", \"role\", \"power_score\"])\n  .toArray();\nconsole.table(features);\n";

export const TsQuickstartMultimodalBytes = "const arrow = await import(\"apache-arrow\");\nconst path = await import(\"node:path\");\nconst { readFile } = await import(\"node:fs/promises\");\n\nconst imagePath = path.resolve(\n  \"../../docs/static/assets/images/quickstart/sir-lancelot.jpg\",\n);\nconst imageBytes = await readFile(imagePath);\nconst imageSchema = new arrow.Schema([\n  new arrow.Field(\"id\", new arrow.Utf8()),\n  new arrow.Field(\"description\", new arrow.Utf8()),\n  new arrow.Field(\"image\", new arrow.Binary()),\n  new arrow.Field(\n    \"vector\",\n    new arrow.FixedSizeList(\n      4,\n      new arrow.Field(\"item\", new arrow.Float32(), true),\n    ),\n  ),\n]);\nconst imageData = lancedb.makeArrowTable(\n  [\n    {\n      id: \"lancelot\",\n      description: \"Portrait of Sir Lancelot\",\n      image: imageBytes,\n      vector: [0.9, 0.1, 0.5, 0.4],\n    },\n  ],\n  { schema: imageSchema },\n);\nconst multimodalTable = await db.createTable(\n  \"character_images\",\n  imageData,\n  { mode: \"overwrite\" },\n);\n";

export const TsQuickstartData = "const data = [\n  {\n    id: \"1\",\n    name: \"King Arthur\",\n    role: \"King\",\n    description: \"Leader of Camelot and wielder of Excalibur.\",\n    stats: { strength: 4, magic: 1, leadership: 5, wisdom: 4 },\n    vector: [0.7, 0.1, 0.9, 0.7],\n  },\n  {\n    id: \"2\",\n    name: \"Merlin\",\n    role: \"Wizard\",\n    description: \"Advisor and prophet with deep magical knowledge.\",\n    stats: { strength: 2, magic: 5, leadership: 4, wisdom: 5 },\n    vector: [0.2, 0.9, 0.4, 0.9],\n  },\n  {\n    id: \"3\",\n    name: \"Sir Lancelot\",\n    role: \"Knight\",\n    description: \"Legendary knight known for courage and combat skill.\",\n    stats: { strength: 5, magic: 1, leadership: 3, wisdom: 3 },\n    vector: [0.9, 0.1, 0.5, 0.4],\n  },\n];\n";

export const TsQuickstartCreateTable = "let table = await db.createTable(\"characters\", data, { mode: \"overwrite\" });\n";

export const TsQuickstartCurateWithMetadata = "const curated = await table\n  .search(queryVector)\n  .where(\"stats.magic >= 4\")\n  .select([\"name\", \"role\", \"description\", \"_distance\"])\n  .limit(2)\n  .toArray();\nconsole.table(curated);\n";

export const TsQuickstartAddFeature = "await table.addColumns([\n  {\n    name: \"power_score\",\n    valueSql:\n      \"cast(((stats.strength + stats.magic + stats.leadership + stats.wisdom) / 4.0) as float)\",\n  },\n]);\n";

export const RsQuickstartVectorSearch1 = "// Search for examples similar to a \"wise magical advisor\"\nlet query_vector = [0.2, 0.8, 0.4, 0.9];\n\nlet result: DataFrame = table\n    .query()\n    .nearest_to(&query_vector)\n    .unwrap()\n    .select(Select::Columns(vec![\n        \"name\".to_string(),\n        \"role\".to_string(),\n        \"description\".to_string(),\n        \"_distance\".to_string(),\n    ]))\n    .limit(2)\n    .execute()\n    .await\n    .unwrap()\n    .into_polars()\n    .await\n    .unwrap();\nprintln!(\"{result:?}\");\n";

export const RsQuickstartQueryFeature = "let features: DataFrame = table\n    .query()\n    .select(Select::Columns(vec![\n        \"name\".to_string(),\n        \"role\".to_string(),\n        \"power_score\".to_string(),\n    ]))\n    .execute()\n    .await\n    .unwrap()\n    .into_polars()\n    .await\n    .unwrap();\nprintln!(\"{features:?}\");\n";

export const RsQuickstartMultimodalBytes = "use std::sync::Arc;\n\nuse arrow_array::{\n    BinaryArray, FixedSizeListArray, LargeStringArray, RecordBatch, RecordBatchIterator,\n};\nuse arrow_schema::{DataType, Field, Schema};\n\nlet image_path = std::path::Path::new(env!(\"CARGO_MANIFEST_DIR\"))\n    .join(\"../../docs/static/assets/images/quickstart/sir-lancelot.jpg\");\nlet image_bytes = std::fs::read(image_path).unwrap();\n\nlet image_schema = Arc::new(Schema::new(vec![\n    Field::new(\"id\", DataType::LargeUtf8, false),\n    Field::new(\"description\", DataType::LargeUtf8, false),\n    Field::new(\"image\", DataType::Binary, false),\n    Field::new(\n        \"vector\",\n        DataType::FixedSizeList(Arc::new(Field::new(\"item\", DataType::Float32, true)), 4),\n        false,\n    ),\n]));\nlet image_vectors = [[0.9_f32, 0.1, 0.5, 0.4]];\nlet image_batch = RecordBatch::try_new(\n    image_schema.clone(),\n    vec![\n        Arc::new(LargeStringArray::from_iter_values([\"lancelot\"])),\n        Arc::new(LargeStringArray::from_iter_values([\n            \"Portrait of Sir Lancelot\",\n        ])),\n        Arc::new(BinaryArray::from_iter_values([image_bytes.as_slice()])),\n        Arc::new(\n            FixedSizeListArray::from_iter_primitive::<Float32Type, _, _>(\n                image_vectors\n                    .iter()\n                    .map(|vector| Some(vector.iter().copied().map(Some).collect::<Vec<_>>())),\n                4,\n            ),\n        ),\n    ],\n)\n.unwrap();\nlet image_reader: Box<dyn arrow_array::RecordBatchReader + Send> = Box::new(\n    RecordBatchIterator::new(vec![Ok(image_batch)].into_iter(), image_schema),\n);\nlet multimodal_table = db\n    .create_table(\"character_images\", image_reader)\n    .mode(CreateTableMode::Overwrite)\n    .execute()\n    .await\n    .unwrap();\n";

export const RsQuickstartDefineStruct = "// Define structs representing the data schema\n#[derive(Debug, Clone, Serialize, Deserialize)]\nstruct Stats {\n    strength: i8,\n    magic: i8,\n    leadership: i8,\n    wisdom: i8,\n}\n\n#[derive(Debug, Clone, Serialize, Deserialize)]\nstruct Character {\n    id: String,\n    name: String,\n    role: String,\n    description: String,\n    stats: Stats,\n    vector: [f32; 4],\n}\n\nfn characters_schema() -> Arc<Schema> {\n    Arc::new(Schema::new(vec![\n        Field::new(\"id\", DataType::LargeUtf8, false),\n        Field::new(\"name\", DataType::LargeUtf8, false),\n        Field::new(\"role\", DataType::LargeUtf8, false),\n        Field::new(\"description\", DataType::LargeUtf8, false),\n        Field::new(\n            \"stats\",\n            DataType::Struct(arrow_schema::Fields::from(vec![\n                Arc::new(Field::new(\"strength\", DataType::Int8, false)),\n                Arc::new(Field::new(\"magic\", DataType::Int8, false)),\n                Arc::new(Field::new(\"leadership\", DataType::Int8, false)),\n                Arc::new(Field::new(\"wisdom\", DataType::Int8, false)),\n            ])),\n            false,\n        ),\n        Field::new(\n            \"vector\",\n            DataType::FixedSizeList(Arc::new(Field::new(\"item\", DataType::Float32, true)), 4),\n            false,\n        ),\n    ]))\n}\n";

export const RsQuickstartData = "let data = vec![\n    Character {\n        id: \"1\".to_string(),\n        name: \"King Arthur\".to_string(),\n        role: \"King\".to_string(),\n        description: \"Leader of Camelot and wielder of Excalibur.\".to_string(),\n        stats: Stats {\n            strength: 4,\n            magic: 1,\n            leadership: 5,\n            wisdom: 4,\n        },\n        vector: [0.7, 0.1, 0.9, 0.7],\n    },\n    Character {\n        id: \"2\".to_string(),\n        name: \"Merlin\".to_string(),\n        role: \"Wizard\".to_string(),\n        description: \"Advisor and prophet with deep magical knowledge.\".to_string(),\n        stats: Stats {\n            strength: 2,\n            magic: 5,\n            leadership: 4,\n            wisdom: 5,\n        },\n        vector: [0.2, 0.9, 0.4, 0.9],\n    },\n    Character {\n        id: \"3\".to_string(),\n        name: \"Sir Lancelot\".to_string(),\n        role: \"Knight\".to_string(),\n        description: \"Legendary knight known for courage and combat skill.\".to_string(),\n        stats: Stats {\n            strength: 5,\n            magic: 1,\n            leadership: 3,\n            wisdom: 3,\n        },\n        vector: [0.9, 0.1, 0.5, 0.4],\n    },\n];\n";

export const RsQuickstartCreateTable = "let schema = characters_schema();\nlet table = db\n    .create_table(\"characters\", characters_to_reader(schema.clone(), &data))\n    .mode(CreateTableMode::Overwrite)\n    .execute()\n    .await\n    .unwrap();\n";

export const RsQuickstartCurateWithMetadata = "let curated: DataFrame = table\n    .query()\n    .nearest_to(&query_vector)\n    .unwrap()\n    .only_if(\"stats.magic >= 4\")\n    .select(Select::Columns(vec![\n        \"name\".to_string(),\n        \"role\".to_string(),\n        \"description\".to_string(),\n        \"_distance\".to_string(),\n    ]))\n    .limit(2)\n    .execute()\n    .await\n    .unwrap()\n    .into_polars()\n    .await\n    .unwrap();\nprintln!(\"{curated:?}\");\n";

export const RsQuickstartAddFeature = "table\n    .add_columns(\n        NewColumnTransform::SqlExpressions(vec![(\n            \"power_score\".to_string(),\n            \"cast(((stats.strength + stats.magic + stats.leadership + stats.wisdom) / 4.0) as float)\"\n                .to_string(),\n        )]),\n        None,\n    )\n    .await\n    .unwrap();\n";

export const PyQuickstartOutputPandas = "# Ensure you run `pip install pandas` beforehand\nresult = table.search(query_vector).limit(2).to_pandas()\nprint(result)\n";

export const PyQuickstartVectorSearch1Async = "# Search for examples similar to a \"wise magical advisor\"\nquery_vector = [0.2, 0.8, 0.4, 0.9]\n\n# Ensure you run `pip install polars` beforehand\nasync_result = await (\n    await async_table.search(query_vector)\n).select([\"name\", \"role\", \"description\", \"_distance\"]).limit(2).to_polars()\nprint(async_result)\n";

export const PyQuickstartVectorSearch1 = "# Search for examples similar to a \"wise magical advisor\"\nquery_vector = [0.2, 0.8, 0.4, 0.9]\n\n# Ensure you run `pip install polars` beforehand\nresult = (\n    table.search(query_vector)\n    .select([\"name\", \"role\", \"description\", \"_distance\"])\n    .limit(2)\n    .to_polars()\n)\nprint(result)\n";

export const PyQuickstartQueryFeature = "features = table.search().select([\"name\", \"role\", \"power_score\"]).to_polars()\nprint(features)\n";

export const PyQuickstartMultimodalBytes = "from pathlib import Path\n\nimage_path = Path(\"docs/static/assets/images/quickstart/sir-lancelot.jpg\")\nimage_bytes = image_path.read_bytes()\n\nmultimodal_table = db.create_table(\n    \"character_images\",\n    data=[\n        {\n            \"id\": \"lancelot\",\n            \"description\": \"Portrait of Sir Lancelot\",\n            \"image\": image_bytes,\n            \"vector\": [0.9, 0.1, 0.5, 0.4],\n        }\n    ],\n    mode=\"overwrite\",\n)\n";

export const PyQuickstartCurateWithMetadata = "curated = (\n    table.search(query_vector)\n    .where(\"stats.magic >= 4\")\n    .select([\"name\", \"role\", \"description\", \"_distance\"])\n    .limit(2)\n    .to_polars()\n)\nprint(curated)\n";

export const PyQuickstartAddFeature = "table.add_columns(\n    {\n        \"power_score\": \"cast(((stats.strength + stats.magic + stats.leadership + stats.wisdom) / 4.0) as float)\"\n    }\n)\n";

export const PyQuickstartCreateTableAsync = "async_table = await async_db.create_table(\n    \"characters\",\n    data=data,\n    mode=\"overwrite\",\n)\n";

export const PyQuickstartCreateTable = "table = db.create_table(\"characters\", data=data, mode=\"overwrite\")\n";

export const PyQuickstartData = "data = [\n    {\n        \"id\": \"1\",\n        \"name\": \"King Arthur\",\n        \"role\": \"King\",\n        \"description\": \"Leader of Camelot and wielder of Excalibur.\",\n        \"stats\": {\"strength\": 4, \"magic\": 1, \"leadership\": 5, \"wisdom\": 4},\n        \"vector\": [0.7, 0.1, 0.9, 0.7],\n    },\n    {\n        \"id\": \"2\",\n        \"name\": \"Merlin\",\n        \"role\": \"Wizard\",\n        \"description\": \"Advisor and prophet with deep magical knowledge.\",\n        \"stats\": {\"strength\": 2, \"magic\": 5, \"leadership\": 4, \"wisdom\": 5},\n        \"vector\": [0.2, 0.9, 0.4, 0.9],\n    },\n    {\n        \"id\": \"3\",\n        \"name\": \"Sir Lancelot\",\n        \"role\": \"Knight\",\n        \"description\": \"Legendary knight known for courage and combat skill.\",\n        \"stats\": {\"strength\": 5, \"magic\": 1, \"leadership\": 3, \"wisdom\": 3},\n        \"vector\": [0.9, 0.1, 0.5, 0.4],\n    },\n]\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 TsConnectEnterpriseQuickstart = "const uri = \"db://your-database-uri\";\nconst apiKey = \"your-api-key\";\nconst region = \"us-east-1\";\nconst hostOverride = \"https://your-enterprise-endpoint.com\";\n\nconst db = await lancedb.connect(uri, {\n  apiKey,\n  region,\n  hostOverride,\n});\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 RsConnectObjectStorage = "let uri = \"s3://your-bucket/path\";\n// You can also use \"gs://your-bucket/path\" or \"az://your-container/path\".\n";

export const RsConnectEnterpriseQuickstart = "let uri = \"db://your-database-uri\";\nlet api_key = \"your-api-key\";\nlet region = \"us-east-1\";\nlet host_override = \"https://your-enterprise-endpoint.com\";\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 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 PyConnectObjectStorage = "import lancedb\n\nuri = \"s3://your-bucket/path\"\n# You can also use \"gs://your-bucket/path\" or \"az://your-container/path\".\ndb = lancedb.connect(uri)\n";

export const PyConnectEnterpriseQuickstart = "uri = \"db://your-database-uri\"\napi_key = \"your-api-key\"\nregion = \"us-east-1\"\nhost_override = \"https://your-enterprise-endpoint.com\"\n\ndb = lancedb.connect(\n    uri=uri,\n    api_key=api_key,\n    region=region,\n    host_override=host_override,\n)\n";

export const PyConnectAsync = "import lancedb\n\nuri = \"ex_lancedb\"\nasync_db = await lancedb.connect_async(uri)\n";

export const PyConnect = "import lancedb\n\nuri = \"ex_lancedb\"\ndb = lancedb.connect(uri)\n";

As described in [the landing page](/), LanceDB provides one data layer for
curation, feature engineering, search and retrieval, and model training. Whether you are preparing
training data, building a RAG or agentic retrieval system, reviewing examples, or adding model-generated
features, you'll work with the same underlying table and search primitives.

Let's get started in just a few steps!

## 1. Install LanceDB

Install LanceDB in your client SDK.

<CodeGroup>
  ```bash pip icon="terminal" theme={"theme":{"light":"vitesse-light","dark":"catppuccin-mocha"}}
  pip install lancedb
  ```

  ```bash uv icon="terminal" theme={"theme":{"light":"vitesse-light","dark":"catppuccin-mocha"}}
  uv add lancedb

  # Or, in an existing virtual environment:
  uv pip install lancedb
  ```

  ```bash TypeScript icon=js theme={"theme":{"light":"vitesse-light","dark":"catppuccin-mocha"}}
  npm install @lancedb/lancedb
  ```

  ```bash Rust icon=Rust theme={"theme":{"light":"vitesse-light","dark":"catppuccin-mocha"}}
  cargo add lancedb
  ```
</CodeGroup>

### Python pre-release builds

To pick up the latest features and bug fixes
before the next stable release, install a pre-release from LanceDB's Fury index.

<CodeGroup>
  ```bash pip icon="terminal" theme={"theme":{"light":"vitesse-light","dark":"catppuccin-mocha"}}
  pip install --pre --extra-index-url https://pypi.fury.io/lancedb/ lancedb
  ```

  ```bash uv icon="terminal" theme={"theme":{"light":"vitesse-light","dark":"catppuccin-mocha"}}
  uv venv
  uv pip install --prerelease allow --index https://pypi.fury.io/lancedb/ lancedb

  # To add to pyproject.toml, use:
  uv add --prerelease allow --index https://pypi.fury.io/lancedb/ lancedb
  ```
</CodeGroup>

<Note>
  Pre-release builds receive the same level of testing as stable releases, but their availability is not guaranteed
  for more than 6 months after release. For real-world workloads, we recommend you use the latest stable release
  as far as possible.
</Note>

## 2. Connect to a LanceDB database

LanceDB supports several URI patterns to connect to a database.

* A local filesystem path (when using it as an embedded library)
* A `db://...` URI (when using LanceDB Enterprise)
* An object storage URI: `s3://...`, `gs://...`, or `az://...` (when connecting directly from the client SDK)

### Connect via local directory path

The simplest way to begin is to use LanceDB as an embedded library. Import LanceDB in your
client SDK of choice and point to a local directory path.

<CodeGroup>
  <CodeBlock filename="Python (sync)" language="Python" icon="python">
    {PyConnect}
  </CodeBlock>

  <CodeBlock filename="Python (async)" language="Python" icon="python">
    {PyConnectAsync}
  </CodeBlock>

  <CodeBlock filename="TypeScript" language="TypeScript" icon="square-js">
    {TsConnect}
  </CodeBlock>

  <CodeBlock filename="Rust" language="Rust" icon="rust">
    { "use lancedb::connect;\n" }

    { "\n" }

    {RsConnect}
  </CodeBlock>
</CodeGroup>

### Connect via object storage URIs

You can also connect directly to object storage from the client SDK:

<CodeGroup>
  <CodeBlock filename="Python (sync)" language="Python" icon="python">
    {PyConnectObjectStorage}
  </CodeBlock>

  <CodeBlock filename="Python (async)" language="Python" icon="python">
    {PyConnectObjectStorageAsync}
  </CodeBlock>

  <CodeBlock filename="TypeScript" language="TypeScript" icon="square-js">
    {TsConnectObjectStorage}
  </CodeBlock>

  <CodeBlock filename="Rust" language="Rust" icon="rust">
    {RsConnectObjectStorage}
  </CodeBlock>
</CodeGroup>

For credentials, endpoints, and provider-specific options, see
[Configuring storage](/storage/configuration).

### Connect to LanceDB Enterprise

If you're using LanceDB Enterprise, you can connect to the remote database using the
`db://` URI along with the API key, region, and cluster endpoint you received from the
LanceDB team. Pass the cluster endpoint via `host_override` so the client routes
requests to your deployment.

<CodeGroup>
  <CodeBlock filename="Python" language="Python" icon="python">
    { "import lancedb\n\n" }

    {PyConnectEnterpriseQuickstart}
  </CodeBlock>

  <CodeBlock filename="TypeScript" language="TypeScript" icon="square-js">
    { "import * as lancedb from \"@lancedb/lancedb\";\n\n" }

    {TsConnectEnterpriseQuickstart}
  </CodeBlock>

  <CodeBlock filename="Rust" language="Rust" icon="rust">
    { "use lancedb::connect;\n\n" }

    {RsConnectEnterpriseQuickstart}
  </CodeBlock>
</CodeGroup>

<Note>
  `host_override` is the full URL of your cluster endpoint, including the scheme
  (`https://`) and a port if your deployment listens on a non-default one
  (e.g. `https://your-enterprise-endpoint.com:443`). If you don't have the
  endpoint, [contact the LanceDB team](mailto:contact@lancedb.com).
</Note>

To learn more about `RemoteTable` semantics and how Enterprise differs operationally from
embedded LanceDB, see the [Enterprise overview](/enterprise).

## 3. Create a new table

Let's create a small table of characters from the kingdom of Camelot. Each row stores source text,
metadata, structured fields, and a vector embedding in the same LanceDB table.

<Info>
  The embeddings we use in this example are synthetic and for demonstration purposes only. In a real AI
  data workflow, you would generate them from text, images, audio, or video using an embedding model of choice.
</Info>

Each row has source text, metadata, structured fields, and a vector:

```json theme={"theme":{"light":"vitesse-light","dark":"catppuccin-mocha"}}
{
  "id": "2",
  "name": "Merlin",
  "role": "Wizard",
  "description": "Advisor and prophet with deep magical knowledge.",
  "stats": { "strength": 2, "magic": 5, "leadership": 4, "wisdom": 5 },
  "vector": [0.2, 0.9, 0.4, 0.9]
}
```

The full raw records are included below:

<Accordion title="View raw character records">
  <CodeGroup>
    <CodeBlock filename="Python (sync)" language="Python" icon="python">
      {PyQuickstartData}
    </CodeBlock>

    <CodeBlock filename="TypeScript" language="TypeScript" icon="square-js">
      {TsQuickstartData}
    </CodeBlock>

    <CodeBlock filename="Rust" language="Rust" icon="rust">
      {RsQuickstartDefineStruct}

      {RsQuickstartData}
    </CodeBlock>
  </CodeGroup>
</Accordion>

You can now create a LanceDB table from those records. The code below creates a LanceDB table
with the appropriate schema and ingests the data.

<CodeGroup>
  <CodeBlock filename="Python (sync)" language="Python" icon="python">
    {PyQuickstartCreateTable}
  </CodeBlock>

  <CodeBlock filename="Python (async)" language="Python" icon="python">
    {PyQuickstartCreateTableAsync}
  </CodeBlock>

  <CodeBlock filename="TypeScript" language="TypeScript" icon="square-js">
    {TsQuickstartCreateTable}
  </CodeBlock>

  <CodeBlock filename="Rust" language="Rust" icon="rust">
    {RsQuickstartCreateTable}
  </CodeBlock>
</CodeGroup>

## 4. Semantic search

Search is a useful capability for all kinds of AI data pipelines. Below, we do a vector similarity
search for samples similar to a "*wise magical advisor*" (transforming the natural language query to
an embedding), and project only the columns needed by the next step.

Search (which requires random access) is a ubiquitous access pattern that appears in many workloads:
whether you're building a RAG or recommendation system, serving agent memory, or curating a training
dataset.

<CodeGroup>
  <CodeBlock filename="Python (sync)" language="Python" icon="python">
    {PyQuickstartVectorSearch1}
  </CodeBlock>

  <CodeBlock filename="Python (async)" language="Python" icon="python">
    {PyQuickstartVectorSearch1Async}
  </CodeBlock>

  <CodeBlock filename="TypeScript" language="TypeScript" icon="square-js">
    {TsQuickstartVectorSearch1}
  </CodeBlock>

  <CodeBlock filename="Rust" language="Rust" icon="rust">
    {RsQuickstartVectorSearch1}
  </CodeBlock>
</CodeGroup>

The example for Python above shows how to convert results to a Polars DataFrame.
Depending on your language, you can collect query results as a list/array of objects or DataFrames
to be used downstream in your application.

<Accordion title="Pandas users in Python can get results as a Pandas DataFrame">
  Use the `to_pandas()` method to convert query results into a Pandas DataFrame.

  <CodeBlock filename="Python" language="Python" icon="python">
    {PyQuickstartOutputPandas}
  </CodeBlock>
</Accordion>

## 5. Curation

Searching for relevant results can be more useful when combined with metadata filters.
In this tiny example, we filter to examples with high `magic` stats.

<CodeGroup>
  <CodeBlock filename="Python" language="Python" icon="python">
    {PyQuickstartCurateWithMetadata}
  </CodeBlock>

  <CodeBlock filename="TypeScript" language="TypeScript" icon="square-js">
    {TsQuickstartCurateWithMetadata}
  </CodeBlock>

  <CodeBlock filename="Rust" language="Rust" icon="rust">
    {RsQuickstartCurateWithMetadata}
  </CodeBlock>
</CodeGroup>

When working with large datasets, it's common to use the same pattern to filter on quality labels,
train/eval splits, numeric fields, categorical values, timestamp windows, or generated tags and labels.

## 6. Add a derived feature

Feature engineering is the process of cleaning up your data and creating new signals that
help your model learn, make better predictions, or your agent retrieve more useful information.
In the example below, we add a `power_score` column from the structured `stats` fields.
Lance supports data evolution, so you can add new columns without rewriting the entire table.

<CodeGroup>
  <CodeBlock filename="Python" language="Python" icon="python">
    {PyQuickstartAddFeature}
  </CodeBlock>

  <CodeBlock filename="TypeScript" language="TypeScript" icon="square-js">
    {TsQuickstartAddFeature}
  </CodeBlock>

  <CodeBlock filename="Rust" language="Rust" icon="rust">
    { "use lancedb::table::NewColumnTransform;\n\n" }

    {RsQuickstartAddFeature}
  </CodeBlock>
</CodeGroup>

Next, you can query a compact view of the new feature:

<CodeGroup>
  <CodeBlock filename="Python" language="Python" icon="python">
    {PyQuickstartQueryFeature}
  </CodeBlock>

  <CodeBlock filename="TypeScript" language="TypeScript" icon="square-js">
    {TsQuickstartQueryFeature}
  </CodeBlock>

  <CodeBlock filename="Rust" language="Rust" icon="rust">
    {RsQuickstartQueryFeature}
  </CodeBlock>
</CodeGroup>

| name         | role   | power\_score |
| ------------ | ------ | ------------ |
| King Arthur  | King   | 3.5          |
| Merlin       | Wizard | 4.0          |
| Sir Lancelot | Knight | 3.0          |

The same workflow is used for data preparation tasks when adding derived features, cached model signals, review scores, or dataset
quality indicators.

## 7. Store multimodal data

Multimodal data is a first-class citizen in LanceDB. Binary data (image, audio, video, etc.) is
stored as blobs or inline Arrow binary types in a LanceDB column, and they benefit from the same
table operations and data versioning semantics as other data types. All the data is governed
in the same table, so you can search, filter, and retrieve multimodal records together with structured
fields, metadata, and embeddings.

In this example, the
[`lancedb/magical_kingdom`](https://huggingface.co/datasets/lancedb/magical_kingdom) dataset stores
character images, descriptions, structured stats, image embeddings, and text embeddings together.

Say we downloaded the image for Sir Lancelot from that dataset locally. You can read the image bytes
in your client SDK and store them in a LanceDB column. The image bytes can be used for downstream tasks
like retrieval, evaluation, or training.

<div style={{ display: "flex", justifyContent: "center" }}>
  <img src="https://mintcdn.com/lancedb-bcbb4faf-weston-feat-streaming-dataset/W6D4SzVTJ5dt-nVb/static/assets/images/quickstart/sir-lancelot.jpg?fit=max&auto=format&n=W6D4SzVTJ5dt-nVb&q=85&s=d799af2dd79a12617529e508075a098f" alt="Sir Lancelot from the lancedb/magical_kingdom dataset" width="320" data-path="static/assets/images/quickstart/sir-lancelot.jpg" />
</div>

These snippets load the local image file and store the bytes in an `image` column:

<CodeGroup>
  <CodeBlock filename="Python" language="Python" icon="python">
    {PyQuickstartMultimodalBytes}
  </CodeBlock>

  <CodeBlock filename="TypeScript" language="TypeScript" icon="square-js">
    {TsQuickstartMultimodalBytes}
  </CodeBlock>

  <CodeBlock filename="Rust" language="Rust" icon="rust">
    {RsQuickstartMultimodalBytes}
  </CodeBlock>
</CodeGroup>

For more examples, see the [multimodal data](/tables/multimodal) section.

## Code

See the full code for these examples (including helper functions) in the
`quickstart` file for the appropriate client language in the
[files provided in the repo](https://github.com/lancedb/docs/tree/main/tests).

## What's next?

You've learned how to install LanceDB, connect, create one table for AI data, retrieve related
examples, curate with metadata, add a derived feature, and represent multimodal records. These same
primitives apply across the AI data lifecycle, from data preparation and feature engineering to
retrieval, evaluation, and training.

Continue to the table and search guides to build on this example with schema options, appends,
updates, versioning, indexing, full-text search, hybrid search, and reranking.

<Columns cols={2}>
  <Card title="Basic table operations" icon="table" href="/tables">
    Build on this quickstart with table creation, updates, and schema tips.
  </Card>

  <Card title="Build a RAG App" icon="search" href="/tutorials/agents/">
    Learn how to build Retrieval-Augmented Generation (RAG) applications using LanceDB.
  </Card>

  <Card title="Indexing" icon="layer-group" href="/indexing/">
    Create vector, full-text, and scalar indexes to speed up queries on larger datasets.
  </Card>

  <Card title="Data loading and shuffles" icon="boxes-stacked" href="/training/">
    Use LanceDB for projected, shuffled, random-access reads in training workflows.
  </Card>
</Columns>
