This is an automated email from the ASF dual-hosted git repository.
jiayu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/sedona-db.git
The following commit(s) were added to refs/heads/main by this push:
new 96fdd77d docs: add iceberg page (#417)
96fdd77d is described below
commit 96fdd77d703b3da82444424619b21b5568a160f8
Author: Matthew Powers <[email protected]>
AuthorDate: Sun Dec 14 01:02:44 2025 -0500
docs: add iceberg page (#417)
---
docs/iceberg.ipynb | 536 +++++++++++++++++++++++++++++++++++++++++++++++++++++
docs/iceberg.md | 331 +++++++++++++++++++++++++++++++++
mkdocs.yml | 1 +
3 files changed, 868 insertions(+)
diff --git a/docs/iceberg.ipynb b/docs/iceberg.ipynb
new file mode 100644
index 00000000..4f014261
--- /dev/null
+++ b/docs/iceberg.ipynb
@@ -0,0 +1,536 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "bfe3c140-3694-40af-8e39-57c0657aac6a",
+ "metadata": {},
+ "source": [
+ "# SedonaDB + Iceberg\n",
+ "\n",
+ "This page demonstrates how to store spatial data in Iceberg tables and
how to query them with SedonaDB.\n",
+ "\n",
+ "You will learn how to create an Iceberg table with a well-known text
(WKT) or well-known binary (WKB) column in an Iceberg table and some of the
advantages of storing geometric data in Iceberg.\n",
+ "\n",
+ "Make sure to run `pip install pyiceberg` to install the required
dependencies for this notebook.\n",
+ "\n",
+ "Let’s start by loading the required dependencies and saving a spatial
dataset in an Iceberg table."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "16ff79eb-5249-47c7-80c9-b0aa88858599",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from pyiceberg.catalog import load_catalog\n",
+ "import sedona.db\n",
+ "import pyarrow as pa\n",
+ "import os"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "cf73a0c0-30d4-4e61-b434-485f10695c2b",
+ "metadata": {},
+ "source": [
+ "## Create an Iceberg table with geometric data\n",
+ "\n",
+ "Start by creating the Iceberg warehouse:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "ab77da72-68cd-4c66-89fa-44280ce7955c",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "os.makedirs(\"/tmp/warehouse\", exist_ok=True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4b35bb19-725c-4da4-a9a7-8866fc31ec9e",
+ "metadata": {},
+ "source": [
+ "Now set up the catalog:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "757f6995-68da-49f3-b2b1-8173876edc05",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "warehouse_path = \"/tmp/warehouse\"\n",
+ "catalog = load_catalog(\n",
+ " \"default\",\n",
+ " **{\n",
+ " \"type\": \"sql\",\n",
+ " \"uri\": f\"sqlite:///{warehouse_path}/pyiceberg_catalog.db\",\n",
+ " \"warehouse\": f\"file://{warehouse_path}\",\n",
+ " },\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f2b00cd7-017a-47c1-a27a-69b905fe135d",
+ "metadata": {},
+ "source": [
+ "Use SedonaDB to read a Parquet file containing country data into a
DataFrame."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "a9a4bd5f-a986-44dc-a787-5d8a80916a8d",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "sd = sedona.db.connect()\n",
+ "\n",
+ "countries = sd.read_parquet(\n",
+ "
\"https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/natural-earth/files/natural-earth_countries_geo.parquet\"\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ee5c39cd-1858-4049-803b-c63cdac82034",
+ "metadata": {},
+ "source": [
+ "Convert all the columns to be plain strings because Iceberg doesn’t
support geometry columns yet:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "68296482-4fd5-41b1-86a1-6915fdd91fd7",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "countries.to_view(\"countries\", True)\n",
+ "df = sd.sql(\"\"\"\n",
+ " select \n",
+ " ARROW_CAST(name, 'Utf8') as name, \n",
+ " ARROW_CAST(continent, 'Utf8') as continent, \n",
+ " ST_AsText(geometry) as geometry_wkt \n",
+ " from countries\n",
+ "\"\"\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "daebb7f0-8ea4-4e98-89b2-e14fe52057c3",
+ "metadata": {},
+ "source": [
+ "The explicit casting with `ARROW_CAST` is necessary because PyIceberg
doesn't support string views.\n",
+ "\n",
+ "Check out the schema of the DataFrame:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "5139d006-81e1-4f45-a844-c7e4f702b91f",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "SedonaSchema with 3 fields:\n",
+ " name: utf8<Utf8>\n",
+ " continent: utf8<Utf8>\n",
+ " geometry_wkt: utf8<Utf8>"
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "df.schema"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "3ad1052a-24ec-4522-b581-6c672d9093c9",
+ "metadata": {},
+ "source": [
+ "Now create a new Iceberg table:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 26,
+ "id": "31c30e61-463d-4e21-bf00-9b40ac633cfe",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from pyiceberg.exceptions import NamespaceAlreadyExistsError\n",
+ "\n",
+ "try:\n",
+ " catalog.create_namespace(\"default\")\n",
+ "except NamespaceAlreadyExistsError:\n",
+ " pass\n",
+ "\n",
+ "if catalog.table_exists(\"default.countries\"):\n",
+ " catalog.drop_table(\"default.countries\")\n",
+ "\n",
+ "table = catalog.create_table(\n",
+ " \"default.countries\",\n",
+ " schema=pa.schema(df.schema),\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "c7c85415-6dbf-4c54-afe9-5e939338e11f",
+ "metadata": {},
+ "source": [
+ "Append the DataFrame to the table:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "id": "9605c683-ee76-458a-8f3d-418608817a49",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "table.append(df.to_arrow_table())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4cfc60c9-02b0-4377-a504-bbd9fbcbf58e",
+ "metadata": {},
+ "source": [
+ "Now let’s see how to read the data with SedonaDB.\n",
+ "\n",
+ "## Read the Iceberg table into SedonaDB via Arrow\n",
+ "\n",
+ "Here’s how to read an Iceberg table into a SedonaDB DataFrame:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "id": "8f3f63e1-9a1f-4d5f-8bc5-01c7ecb57549",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "table = catalog.load_table(\"default.countries\")\n",
+ "arrow_table = table.scan().to_arrow()\n",
+ "df = sd.create_data_frame(arrow_table)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "00343bb6-c486-4723-8b29-40566ac15e3e",
+ "metadata": {},
+ "source": [
+ "The Iceberg table is first exposed as an arrow table and then read into a
SedonaDB DataFrame.\n",
+ "\n",
+ "Now view the contents of the SedonaDB DataFrame:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 17,
+ "id": "f6573e68-975d-4285-999d-43bd4ea8fdd8",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+
"┌─────────────────────────────┬───────────┬────────────────────────────────────────────────────────┐\n",
+ "│ name ┆ continent ┆
geom │\n",
+ "│ utf8 ┆ utf8 ┆
geometry │\n",
+
"╞═════════════════════════════╪═══════════╪════════════════════════════════════════════════════════╡\n",
+ "│ Fiji ┆ Oceania ┆ MULTIPOLYGON(((180
-16.067132663642447,180 -16.555216… │\n",
+
"├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤\n",
+ "│ United Republic of Tanzania ┆ Africa ┆ POLYGON((33.90371119710453
-0.9500000000000001,34.072… │\n",
+
"├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤\n",
+ "│ Western Sahara ┆ Africa ┆ POLYGON((-8.665589565454809
27.656425889592356,-8.665… │\n",
+
"└─────────────────────────────┴───────────┴────────────────────────────────────────────────────────┘\n"
+ ]
+ }
+ ],
+ "source": [
+ "df.to_view(\"my_table\", True)\n",
+ "res = sd.sql(\"\"\"\n",
+ "SELECT\n",
+ " name,\n",
+ " continent,\n",
+ " ST_GeomFromWKT(geometry_wkt) as geom\n",
+ "from my_table\n",
+ "\"\"\")\n",
+ "res.show(3)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "efe2c02c-6453-4819-9a7f-7a5e30309090",
+ "metadata": {},
+ "source": [
+ "You can see that the geom column contains the geometry type, which
enables spatial analysis of the data.\n",
+ "\n",
+ "The geometry data is stored as WKT, which isn't as efficient as WKB. The
example that follows demonstrates how to store WKB in Iceberg tables.\n",
+ "\n",
+ "## Future Iceberg geography/geometry work\n",
+ "\n",
+ "Iceberg added support for geometry and geography columns in the v3
spec.\n",
+ "\n",
+ "The Iceberg v3 implementation has not been released yet, and it the v3
spec hasn't started in Iceberg Rust. Here is [the open
issue](https://github.com/apache/iceberg-rust/issues/1884) to add geo support
to Iceberg Rust.\n",
+ "\n",
+ "It’s best to manually persist the bbox information of files in your
Iceberg table if you’re storing geometric data as WKT or WKB. \n",
+ "\n",
+ "## Create an Iceberg table with WKB and bbox\n",
+ "\n",
+ "Let’s see how to create an Iceberg table with a WKB and bbox columns to
allow for faster spatial analyses.\n",
+ "\n",
+ "Start by creating the cities DataFrame."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "id": "a466349e-98f9-4e0a-9c7a-fddf451b18fa",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "cities = sd.read_parquet(\n",
+ "
\"https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/natural-earth/files/natural-earth_cities_geo.parquet\"\n",
+ ")\n",
+ "cities.to_view(\"cities\", True)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8317ca27-f69c-445f-9477-c18c91cd4a1c",
+ "metadata": {},
+ "source": [
+ "Now write the DataFrame to an Iceberg table with bbox columns:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 19,
+ "id": "0aeb9dd6-cccb-4cec-a649-34846194ad12",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "df = sd.sql(\"\"\"\n",
+ "select \n",
+ " ARROW_CAST(name, 'Utf8') as name, \n",
+ " ARROW_CAST(ST_AsBinary(geometry), 'Binary') as geometry_wkb,\n",
+ " ST_XMin(geometry) as bbox_xmin,\n",
+ " ST_YMin(geometry) as bbox_ymin,\n",
+ " ST_XMax(geometry) as bbox_xmax,\n",
+ " ST_YMax(geometry) as bbox_ymax\n",
+ "from cities\n",
+ "\"\"\")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "id": "17a5f37a-01f5-4913-adfb-129213355474",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "if catalog.table_exists(\"default.cities\"):\n",
+ " catalog.drop_table(\"default.cities\")\n",
+ "\n",
+ "table = catalog.create_table(\n",
+ " \"default.cities\",\n",
+ " schema=pa.schema(df.schema),\n",
+ ")"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "id": "a018252f-9ca5-49e7-a103-1b7451ba05b1",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "table.append(df.to_arrow_table())"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "ad8bd437-ce73-46f5-8ace-e2e9056c460f",
+ "metadata": {},
+ "source": [
+ "Load the `cities` table into a DataFrame with SedonaDB."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "id": "e86fcb62-f1fd-43ca-9aaf-54e60516cc5e",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+
"┌──────────────┬───────────────────────────┬─────────────┬─────────────┬─────────────┬─────────────┐\n",
+ "│ name ┆ geometry_wkb ┆ bbox_xmin ┆ bbox_ymin
┆ bbox_xmax ┆ bbox_ymax │\n",
+ "│ utf8 ┆ binary ┆ float64 ┆ float64
┆ float64 ┆ float64 │\n",
+
"╞══════════════╪═══════════════════════════╪═════════════╪═════════════╪═════════════╪═════════════╡\n",
+ "│ Vatican City ┆ 010100000054e57b4622e828… ┆ 12.4533865 ┆ 41.9032822
┆ 12.4533865 ┆ 41.9032822 │\n",
+
"├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤\n",
+ "│ San Marino ┆ 0101000000dcb122b42fe228… ┆ 12.4417702 ┆ 43.9360958
┆ 12.4417702 ┆ 43.9360958 │\n",
+
"├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤\n",
+ "│ Vaduz ┆ 01010000006dae9ae7880823… ┆ 9.5166695 ┆ 47.1337238
┆ 9.5166695 ┆ 47.1337238 │\n",
+
"├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤\n",
+ "│ Lobamba ┆ 01010000007bcb8b0233333f… ┆ 31.1999971 ┆ -26.4666675
┆ 31.1999971 ┆ -26.4666675 │\n",
+
"├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤\n",
+ "│ Luxembourg ┆ 0101000000c08d39741f8518… ┆ 6.1300028 ┆ 49.6116604
┆ 6.1300028 ┆ 49.6116604 │\n",
+
"├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤\n",
+ "│ Palikir ┆ 0101000000b237e796ccc463… ┆ 158.1499743 ┆ 6.9166437
┆ 158.1499743 ┆ 6.9166437 │\n",
+
"├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤\n",
+ "│ Majuro ┆ 010100000027ef2df6286c65… ┆ 171.3800002 ┆ 7.1030043
┆ 171.3800002 ┆ 7.1030043 │\n",
+
"├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤\n",
+ "│ Funafuti ┆ 0101000000be28e6c5ee6666… ┆ 179.2166471 ┆ -8.516652
┆ 179.2166471 ┆ -8.516652 │\n",
+
"├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤\n",
+ "│ Melekeok ┆ 0101000000749b70af0cd460… ┆ 134.6265485 ┆ 7.4873962
┆ 134.6265485 ┆ 7.4873962 │\n",
+
"├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤\n",
+ "│ Bir Lehlou ┆ 0101000000f4d3c963174e23… ┆ -9.6525222 ┆ 26.1191667
┆ -9.6525222 ┆ 26.1191667 │\n",
+
"└──────────────┴───────────────────────────┴─────────────┴─────────────┴─────────────┴─────────────┘\n"
+ ]
+ }
+ ],
+ "source": [
+ "table = catalog.load_table(\"default.cities\")\n",
+ "arrow_table = table.scan().to_arrow()\n",
+ "df = sd.create_data_frame(arrow_table)\n",
+ "df.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "id": "e66a151c-7dda-4c98-9548-f8ae373476c5",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "name: string\n",
+ "geometry_wkb: binary\n",
+ "bbox_xmin: double\n",
+ "bbox_ymin: double\n",
+ "bbox_xmax: double\n",
+ "bbox_ymax: double"
+ ]
+ },
+ "execution_count": 23,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "arrow_table.schema"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7ac7c3c4-0e5c-45e3-b09d-aefa57565e6e",
+ "metadata": {},
+ "source": [
+ "Read the Iceberg table and filter it to only include cities in the
eastern half of North America."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "id": "69c1922d-18b1-427a-b677-f77fed057848",
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from pyiceberg.expressions import And, GreaterThanOrEqual,
LessThanOrEqual\n",
+ "\n",
+ "filter_expr = And(\n",
+ " GreaterThanOrEqual(\"bbox_xmax\", -97.0),\n",
+ " LessThanOrEqual(\"bbox_xmin\", -67.0),\n",
+ " GreaterThanOrEqual(\"bbox_ymax\", 25.0),\n",
+ " LessThanOrEqual(\"bbox_ymin\", 50.0),\n",
+ ")\n",
+ "\n",
+ "arrow_table = table.scan(row_filter=filter_expr).to_arrow()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "id": "348fdd14-8c4f-4ddf-809b-59d9b9feb3e9",
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "┌──────────────────┬──────────────────────────────────────────────┐\n",
+ "│ name ┆ geom │\n",
+ "│ utf8 ┆ geometry │\n",
+ "╞══════════════════╪══════════════════════════════════════════════╡\n",
+ "│ Ottawa ┆ POINT(-75.7019612 45.4186427) │\n",
+ "├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤\n",
+ "│ Nassau ┆ POINT(-77.3500438 25.0833901) │\n",
+ "├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤\n",
+ "│ Houston ┆ POINT(-95.34843625672217 29.741272831862542) │\n",
+ "├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤\n",
+ "│ Miami ┆ POINT(-80.2260519 25.7895566) │\n",
+ "├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤\n",
+ "│ Atlanta ┆ POINT(-84.36764186571386 33.73945728378348) │\n",
+ "├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤\n",
+ "│ Chicago ┆ POINT(-87.63523655322338 41.847961283364114) │\n",
+ "├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤\n",
+ "│ Toronto ┆ POINT(-79.38945855491194 43.66464454743429) │\n",
+ "├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤\n",
+ "│ Washington, D.C. ┆ POINT(-77.0113644 38.9014952) │\n",
+ "├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤\n",
+ "│ New York ┆ POINT(-73.99571754361698 40.72156174972766) │\n",
+ "└──────────────────┴──────────────────────────────────────────────┘\n"
+ ]
+ }
+ ],
+ "source": [
+ "df = sd.create_data_frame(arrow_table)\n",
+ "\n",
+ "df.to_view(\"us_east_cities\", True)\n",
+ "sd.sql(\"select name, ST_GeomFromWKB(geometry_wkb) as geom from
us_east_cities\").show()"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.12.4"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/docs/iceberg.md b/docs/iceberg.md
new file mode 100644
index 00000000..af03d5cc
--- /dev/null
+++ b/docs/iceberg.md
@@ -0,0 +1,331 @@
+<!---
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+# SedonaDB + Iceberg
+
+This page demonstrates how to store spatial data in Iceberg tables and how to
query them with SedonaDB.
+
+You will learn how to create an Iceberg table with a well-known text (WKT) or
well-known binary (WKB) column in an Iceberg table and some of the advantages
of storing geometric data in Iceberg.
+
+Make sure to run `pip install pyiceberg` to install the required dependencies
for this notebook.
+
+Let’s start by loading the required dependencies and saving a spatial dataset
in an Iceberg table.
+
+
+```python
+from pyiceberg.catalog import load_catalog
+import sedona.db
+import pyarrow as pa
+import os
+```
+
+## Create an Iceberg table with geometric data
+
+Start by creating the Iceberg warehouse:
+
+
+```python
+os.makedirs("/tmp/warehouse", exist_ok=True)
+```
+
+Now set up the catalog:
+
+
+```python
+warehouse_path = "/tmp/warehouse"
+catalog = load_catalog(
+ "default",
+ **{
+ "type": "sql",
+ "uri": f"sqlite:///{warehouse_path}/pyiceberg_catalog.db",
+ "warehouse": f"file://{warehouse_path}",
+ },
+)
+```
+
+Use SedonaDB to read a Parquet file containing country data into a DataFrame.
+
+
+```python
+sd = sedona.db.connect()
+
+countries = sd.read_parquet(
+
"https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/natural-earth/files/natural-earth_countries_geo.parquet"
+)
+```
+
+Convert all the columns to be plain strings because Iceberg doesn’t support
geometry columns yet:
+
+
+```python
+countries.to_view("countries", True)
+df = sd.sql("""
+ select
+ ARROW_CAST(name, 'Utf8') as name,
+ ARROW_CAST(continent, 'Utf8') as continent,
+ ST_AsText(geometry) as geometry_wkt
+ from countries
+""")
+```
+
+The explicit casting with `ARROW_CAST` is necessary because PyIceberg doesn't
support string views.
+
+Check out the schema of the DataFrame:
+
+
+```python
+df.schema
+```
+
+
+
+
+ SedonaSchema with 3 fields:
+ name: utf8<Utf8>
+ continent: utf8<Utf8>
+ geometry_wkt: utf8<Utf8>
+
+
+
+Now create a new Iceberg table:
+
+
+```python
+from pyiceberg.exceptions import NamespaceAlreadyExistsError
+
+try:
+ catalog.create_namespace("default")
+except NamespaceAlreadyExistsError:
+ pass
+
+if catalog.table_exists("default.countries"):
+ catalog.drop_table("default.countries")
+
+table = catalog.create_table(
+ "default.countries",
+ schema=pa.schema(df.schema),
+)
+```
+
+Append the DataFrame to the table:
+
+
+```python
+table.append(df.to_arrow_table())
+```
+
+Now let’s see how to read the data with SedonaDB.
+
+## Read the Iceberg table into SedonaDB via Arrow
+
+Here’s how to read an Iceberg table into a SedonaDB DataFrame:
+
+
+```python
+table = catalog.load_table("default.countries")
+arrow_table = table.scan().to_arrow()
+df = sd.create_data_frame(arrow_table)
+```
+
+The Iceberg table is first exposed as an arrow table and then read into a
SedonaDB DataFrame.
+
+Now view the contents of the SedonaDB DataFrame:
+
+
+```python
+df.to_view("my_table", True)
+res = sd.sql("""
+SELECT
+ name,
+ continent,
+ ST_GeomFromWKT(geometry_wkt) as geom
+from my_table
+""")
+res.show(3)
+```
+
+
┌─────────────────────────────┬───────────┬────────────────────────────────────────────────────────┐
+ │ name ┆ continent ┆ geom
│
+ │ utf8 ┆ utf8 ┆
geometry │
+
╞═════════════════════════════╪═══════════╪════════════════════════════════════════════════════════╡
+ │ Fiji ┆ Oceania ┆ MULTIPOLYGON(((180
-16.067132663642447,180 -16.555216… │
+
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ │ United Republic of Tanzania ┆ Africa ┆ POLYGON((33.90371119710453
-0.9500000000000001,34.072… │
+
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ │ Western Sahara ┆ Africa ┆ POLYGON((-8.665589565454809
27.656425889592356,-8.665… │
+
└─────────────────────────────┴───────────┴────────────────────────────────────────────────────────┘
+
+
+You can see that the geom column contains the geometry type, which enables
spatial analysis of the data.
+
+The geometry data is stored as WKT, which isn't as efficient as WKB. The
example that follows demonstrates how to store WKB in Iceberg tables.
+
+## Future Iceberg geography/geometry work
+
+Iceberg added support for geometry and geography columns in the v3 spec.
+
+The Iceberg v3 implementation has not been released yet, and it the v3 spec
hasn't started in Iceberg Rust. Here is [the open
issue](https://github.com/apache/iceberg-rust/issues/1884) to add geo support
to Iceberg Rust.
+
+It’s best to manually persist the bbox information of files in your Iceberg
table if you’re storing geometric data as WKT or WKB.
+
+## Create an Iceberg table with WKB and bbox
+
+Let’s see how to create an Iceberg table with a WKB and bbox columns to allow
for faster spatial analyses.
+
+Start by creating the cities DataFrame.
+
+
+```python
+cities = sd.read_parquet(
+
"https://raw.githubusercontent.com/geoarrow/geoarrow-data/v0.2.0/natural-earth/files/natural-earth_cities_geo.parquet"
+)
+cities.to_view("cities", True)
+```
+
+Now write the DataFrame to an Iceberg table with bbox columns:
+
+
+```python
+df = sd.sql("""
+select
+ ARROW_CAST(name, 'Utf8') as name,
+ ARROW_CAST(ST_AsBinary(geometry), 'Binary') as geometry_wkb,
+ ST_XMin(geometry) as bbox_xmin,
+ ST_YMin(geometry) as bbox_ymin,
+ ST_XMax(geometry) as bbox_xmax,
+ ST_YMax(geometry) as bbox_ymax
+from cities
+""")
+```
+
+
+```python
+if catalog.table_exists("default.cities"):
+ catalog.drop_table("default.cities")
+
+table = catalog.create_table(
+ "default.cities",
+ schema=pa.schema(df.schema),
+)
+```
+
+
+```python
+table.append(df.to_arrow_table())
+```
+
+Load the `cities` table into a DataFrame with SedonaDB.
+
+
+```python
+table = catalog.load_table("default.cities")
+arrow_table = table.scan().to_arrow()
+df = sd.create_data_frame(arrow_table)
+df.show()
+```
+
+
┌──────────────┬───────────────────────────┬─────────────┬─────────────┬─────────────┬─────────────┐
+ │ name ┆ geometry_wkb ┆ bbox_xmin ┆ bbox_ymin ┆
bbox_xmax ┆ bbox_ymax │
+ │ utf8 ┆ binary ┆ float64 ┆ float64 ┆
float64 ┆ float64 │
+
╞══════════════╪═══════════════════════════╪═════════════╪═════════════╪═════════════╪═════════════╡
+ │ Vatican City ┆ 010100000054e57b4622e828… ┆ 12.4533865 ┆ 41.9032822 ┆
12.4533865 ┆ 41.9032822 │
+
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ │ San Marino ┆ 0101000000dcb122b42fe228… ┆ 12.4417702 ┆ 43.9360958 ┆
12.4417702 ┆ 43.9360958 │
+
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ │ Vaduz ┆ 01010000006dae9ae7880823… ┆ 9.5166695 ┆ 47.1337238 ┆
9.5166695 ┆ 47.1337238 │
+
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ │ Lobamba ┆ 01010000007bcb8b0233333f… ┆ 31.1999971 ┆ -26.4666675 ┆
31.1999971 ┆ -26.4666675 │
+
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ │ Luxembourg ┆ 0101000000c08d39741f8518… ┆ 6.1300028 ┆ 49.6116604 ┆
6.1300028 ┆ 49.6116604 │
+
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ │ Palikir ┆ 0101000000b237e796ccc463… ┆ 158.1499743 ┆ 6.9166437 ┆
158.1499743 ┆ 6.9166437 │
+
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ │ Majuro ┆ 010100000027ef2df6286c65… ┆ 171.3800002 ┆ 7.1030043 ┆
171.3800002 ┆ 7.1030043 │
+
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ │ Funafuti ┆ 0101000000be28e6c5ee6666… ┆ 179.2166471 ┆ -8.516652 ┆
179.2166471 ┆ -8.516652 │
+
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ │ Melekeok ┆ 0101000000749b70af0cd460… ┆ 134.6265485 ┆ 7.4873962 ┆
134.6265485 ┆ 7.4873962 │
+
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ │ Bir Lehlou ┆ 0101000000f4d3c963174e23… ┆ -9.6525222 ┆ 26.1191667 ┆
-9.6525222 ┆ 26.1191667 │
+
└──────────────┴───────────────────────────┴─────────────┴─────────────┴─────────────┴─────────────┘
+
+
+
+```python
+arrow_table.schema
+```
+
+
+
+
+ name: string
+ geometry_wkb: binary
+ bbox_xmin: double
+ bbox_ymin: double
+ bbox_xmax: double
+ bbox_ymax: double
+
+
+
+Read the Iceberg table and filter it to only include cities in the eastern
half of North America.
+
+
+```python
+from pyiceberg.expressions import And, GreaterThanOrEqual, LessThanOrEqual
+
+filter_expr = And(
+ GreaterThanOrEqual("bbox_xmax", -97.0),
+ LessThanOrEqual("bbox_xmin", -67.0),
+ GreaterThanOrEqual("bbox_ymax", 25.0),
+ LessThanOrEqual("bbox_ymin", 50.0),
+)
+
+arrow_table = table.scan(row_filter=filter_expr).to_arrow()
+```
+
+
+```python
+df = sd.create_data_frame(arrow_table)
+
+df.to_view("us_east_cities", True)
+sd.sql("select name, ST_GeomFromWKB(geometry_wkb) as geom from
us_east_cities").show()
+```
+
+ ┌──────────────────┬──────────────────────────────────────────────┐
+ │ name ┆ geom │
+ │ utf8 ┆ geometry │
+ ╞══════════════════╪══════════════════════════════════════════════╡
+ │ Ottawa ┆ POINT(-75.7019612 45.4186427) │
+ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ │ Nassau ┆ POINT(-77.3500438 25.0833901) │
+ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ │ Houston ┆ POINT(-95.34843625672217 29.741272831862542) │
+ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ │ Miami ┆ POINT(-80.2260519 25.7895566) │
+ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ │ Atlanta ┆ POINT(-84.36764186571386 33.73945728378348) │
+ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ │ Chicago ┆ POINT(-87.63523655322338 41.847961283364114) │
+ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ │ Toronto ┆ POINT(-79.38945855491194 43.66464454743429) │
+ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ │ Washington, D.C. ┆ POINT(-77.0113644 38.9014952) │
+ ├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
+ │ New York ┆ POINT(-73.99571754361698 40.72156174972766) │
+ └──────────────────┴──────────────────────────────────────────────┘
diff --git a/mkdocs.yml b/mkdocs.yml
index 4af02863..f169c866 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -50,6 +50,7 @@ nav:
- Overture Examples: overture-examples.md
- CRS Examples: crs-examples.md
- Delta Lake: delta-lake.md
+ - Iceberg: iceberg.md
- Working with Parquet Files: working-with-parquet-files.md
- Working with SQL in SedonaDB: working-with-sql-sedonadb.md
- Contributors Guide: contributors-guide.md