> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wherobots.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Spatial Filter Push-down for Rasters

WherobotsDB supports spatial filter push-down for rasters. When it writes data files containing raster columns, WherobotsDB records the WGS84 bounding box of the rasters in each file, and uses these bounds to skip unrelated data files when running raster spatial filters such as `RS_Intersects`, `RS_Contains` and `RS_Within`. This can greatly reduce the amount of data that needs to be processed by the application, and thus improve the performance of the application. Spatial filter push-down works for both in-db rasters and out-db rasters.

## Spatial Filter Push-down on Partitioned Tables

Raster spatial filter push-down works best on raster tables partitioned by location-related columns. For example, if you have a table containing rasters of different cities, you can partition the table by the city name column, so that the rasters of the same city will be stored in the same partition. This will make the spatial filter push-down more effective.

Another example is to partition the table by SRID when the rasters in your table have UTM coordinate reference system and are scattered in different UTM zones. Here is an example of partitioning EuroSAT dataset by SRID to optimize spatial range queries:

**Python**

```python theme={"system"}
# Create a table partitioned by SRID
sedona.sql("""
CREATE TABLE org_catalog.test_db.eurosat_ms_srid (
    path STRING,
    length BIGINT,
    rast RASTER,
    srid INT
) USING iceberg
PARTITIONED BY (srid)
""")

# Load rasters from GeoTIFF files
df_binary = sedona.read.format("binaryFile")\
    .option("pathGlobFilter", "*.tif")\
    .option("recursiveFileLookup", "true")\
    .load('s3://wherobots-examples/data/eurosat_small')
df_geotiff = df_binary.withColumn("rast", expr("RS_FromGeoTiff(content)"))\
    .select("path", "length", "rast")

# Append the rasters to the table, sorted by SRID
df_geotiff.withColumn("srid", expr("RS_SRID(rast)"))\
    .sort("srid")\
    .writeTo("org_catalog.test_db.eurosat_ms_srid").append()
```

**Scala**

```scala theme={"system"}
// Create a table partitioned by SRID
sedona.sql("""
CREATE TABLE org_catalog.test_db.eurosat_ms_srid (
    path STRING,
    length BIGINT,
    rast RASTER,
    srid INT
) USING iceberg
PARTITIONED BY (srid)
""")

// Load rasters from GeoTIFF files
val df_binary = sedona.read.format("binaryFile")
    .option("pathGlobFilter", "*.tif")
    .option("recursiveFileLookup", "true")
    .load("s3://wherobots-examples/data/eurosat_small")

val df_geotiff = df_binary.withColumn("rast", expr("RS_FromGeoTiff(content)"))
    .select("path", "length", "rast")

// Append the rasters to the table, sorted by SRID
df_geotiff.withColumn("srid", expr("RS_SRID(rast)"))
    .sort("srid")
    .writeTo("org_catalog.test_db.eurosat_ms_srid").append()
```

**Java**

```java theme={"system"}
// Create a table partitioned by SRID
sedona.sql("CREATE TABLE org_catalog.test_db.eurosat_ms_srid ("
    + "path STRING, length BIGINT, rast RASTER, srid INT) USING iceberg "
    + "PARTITIONED BY (srid)");

// Load rasters from GeoTIFF files
Dataset<Row> df_binary = sedona.read().format("binaryFile")
    .option("pathGlobFilter", "*.tif")
    .option("recursiveFileLookup", "true")
    .load("s3://wherobots-examples/data/eurosat_small");

Dataset<Row> df_geotiff = df_binary.withColumn("rast", expr("RS_FromGeoTiff(content)"))
    .select("path", "length", "rast");

// Append the rasters to the table, sorted by SRID
df_geotiff.withColumn("srid", expr("RS_SRID(rast)"))
    .sort("srid")
    .writeTo("org_catalog.test_db.eurosat_ms_srid").append();
```

Subsequent queries such as

```sql theme={"system"}
SELECT * FROM org_catalog.test_db.eurosat_ms_srid WHERE RS_Intersects(rast, ...)
```

will be much faster than the same query on a non-partitioned table.

## Clustering by Raster Columns

WherobotsDB also supports clustering the data by raster columns. This can be achieved by using `CREATE SPATIAL INDEX` statement to rewrite the table and cluster the data by the raster column. For example, we can cluster the data in table `wherobots.db.test_table` by the raster column `rast`:

```sql theme={"system"}
CREATE SPATIAL INDEX FOR wherobots.db.test_table USING hilbert(rast, 10);
```

This is only recommended for the following scenarios:

* The original table does not have a good column for partitioning.
* The table contains out-db rasters or very small in-db rasters.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.