Skip to content
28 changes: 28 additions & 0 deletions docs/lakehouse-generic-lance-table.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,3 +302,31 @@ done

Other table operations (load, alter, drop, truncate) follow standard relational catalog patterns. See [Table Operations](./manage-relational-metadata-using-gravitino.md#table-operations) for details.

### Using Lance table with MinIO
To use Lance tables stored in MinIO with Gravitino, ensure that the MinIO storage backend is properly configured. Below is an example of how to set up and use Lance tables with MinIO.

```shell
curl -X POST -H "Accept: application/vnd.gravitino.v1+json" \
-H "Content-Type: application/json" -d '{
"name": "lance_table",
"comment": "Example Lance table",
"columns": [
{
"name": "id",
"type": "integer",
"comment": "Primary identifier",
"nullable": false
}
],
"properties": {
"format": "lance",
"location": "s3://bucket1/lance_table",
"lance.storage.access_key_id": "ak",
"lance.storage.endpoint": "http://minio:9000",
"lance.storage.secret_access_key": "sk",
"lance.storage.allow_http": "true"
}
}' http://localhost:8090/api/metalakes/test/catalogs/lance_catalog/schemas/schema/tables

```

112 changes: 112 additions & 0 deletions docs/lance-rest-spark-ray-integration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
---
title: "Lance REST integration with Spark and Ray"
slug: /lance-rest-spark-ray-integration
keywords:
- lance
- lance-rest
- spark
- ray
- integration
license: "This software is licensed under the Apache License version 2."
---

## Overview

This guide shows how to use the Lance REST service from Apache Gravitino with the Lance Spark connector (`lance-spark`) and the Lance Ray connector (`lance-ray`). It builds on the Lance REST service setup described in [Lance REST service](./lance-rest-service).

## Compatibility matrix

| Gravitino version (Lance REST) | Supported lance-spark versions | Supported lance-ray versions |
|--------------------------------|--------------------------------|------------------------------|
| 1.1.1 | 0.0.10 – 0.0.15 | 0.0.6 – 0.0.8 |

:::note
- Update this matrix when newer Gravitino versions (for example 1.2.0) are released.
- Align connector versions with the Lance REST service bundled in the target release.
:::

## Prerequisites

- Gravitino server running with Lance REST service enabled (default endpoint: `http://localhost:9101/lance`).
- A Lance catalog created in Gravitino, for example `lance_catalog`.
- Downloaded `lance-spark` bundle JAR that matches your Spark version (set the absolute path in the examples below).
- Python environments with required packages:
- Spark: `pyspark`
- Ray: `ray`, `lance-namespace`, `lance-ray`

## Using Lance REST with Spark

The example below starts a local PySpark session that talks to Lance REST and creates a table through Spark SQL.

```python
from pyspark.sql import SparkSession
import os
import logging
logging.basicConfig(level=logging.INFO)

# Point to your downloaded lance-spark bundle.
os.environ["PYSPARK_SUBMIT_ARGS"] = "--jars /path/to/lance-spark-bundle-3.5_2.12-0.0.15.jar --conf \"spark.driver.extraJavaOptions=--add-opens=java.base/sun.nio.ch=ALL-UNNAMED\" --conf \"spark.executor.extraJavaOptions=--add-opens=java.base/sun.nio.ch=ALL-UNNAMED\" --master local[1] pyspark-shell"

# Create the Lance catalog named "lance_catalog" in Gravitino beforehand.
spark = SparkSession.builder \
.appName("lance_rest_example") \
.config("spark.sql.catalog.lance", "com.lancedb.lance.spark.LanceNamespaceSparkCatalog") \
.config("spark.sql.catalog.lance.impl", "rest") \
.config("spark.sql.catalog.lance.uri", "http://localhost:9101/lance") \
.config("spark.sql.catalog.lance.parent", "lance_catalog") \
.config("spark.sql.defaultCatalog", "lance") \
.getOrCreate()

spark.sparkContext.setLogLevel("DEBUG")

# Create schema and table, write, then read data.
spark.sql("create database schema")
spark.sql("""
create table schema.sample(id int, score float)
USING lance
LOCATION '/tmp/schema/sample.lance/'
TBLPROPERTIES ('format' = 'lance')
""")
spark.sql("""
insert into schema.sample values(1, 1.1)
""")
spark.sql("select * from schema.sample").show()
```

:::note
- Keep the Lance REST service reachable from Spark executors.
- Replace the JAR path with the actual location on your machine or cluster.
- Add your own JVM debugging flags only when needed.
:::

## Using Lance REST with Ray

The snippet below writes and reads a Lance dataset through the Lance REST namespace.

```python
import ray
import lance_namespace as ln
from lance_ray import read_lance, write_lance

ray.init()

namespace = ln.connect("rest", {"uri": "http://localhost:9101/lance"})

data = ray.data.range(1000).map(lambda row: {"id": row["id"], "value": row["id"] * 2})

write_lance(data, namespace=namespace, table_id=["lance_catalog", "schema", "my_table"])
ray_dataset = read_lance(namespace=namespace, table_id=["lance_catalog", "schema", "my_table"])

result = ray_dataset.filter(lambda row: row["value"] < 100).count()
print(f"Filtered count: {result}")
```

:::note
- Ensure the target Lance catalog (`lance_catalog`) and schema (`schema`) already exist in Gravitino.
- The table path is represented as `["catalog", "schema", "table"]` when using Lance Ray helpers.
:::

## Troubleshooting

- **TypeError `_BaseLanceDatasink.on_write_start()` when using Ray 2.53.3**: downgrade Ray to `2.40.0` (for example, `pip install 'ray==2.40.0'`).
- **ValueError “too many values to unpack” from `lance_ray` datasink**: this is a known issue in `lance-ray`; track progress at [lance-format/lance-ray#68](https://github.com/lance-format/lance-ray/issues/68).