Vector Writer
vector_gbx — pyogrio-backed, pure-Python DataSource V2 writer. It is the generic
catch-all vector writer: pass any OGR-supported driver via driverName and it
round-trips with the matching vector_gbx reader. For common formats, use the named
writers instead:
- Shapefile Writer —
shapefile_gbx(OGR driver:ESRI Shapefile) - GeoJSON Writer —
geojson_gbx(OGR driver:GeoJSON) - GeoPackage Writer —
gpkg_gbx(OGR driver:GPKG) - GeoDatabase Writer —
file_gdb_gbx(OGR driver:OpenFileGDB)
- Large datasets: this writer assembles output on a single node (sequential driver merge);
for very large outputs, use a classic cluster (high-memory Serverless does not help
here) or switch to the scalable
geojsonl_gbx/gpkg_gbxwriters. See Choosing a writer for large datasets. - Tier & compute: the lightweight (
*_gbx) writers need no JAR or init script and are the only option on Serverless, standard (shared), and ARM clusters. The heavyweight raster/PMTiles writers require a classic x86 cluster (JAR + GDAL init script). Your compute usually decides the tier — then data scale. See Benchmarking for timings and methodology.
- Register first — call
register(spark)once before using any*_gbxformat (see the Writers Overview). - Lightweight-only — this single-file writer isn't implemented in the heavyweight tier;
for output in both tiers, use the sharded GeoJSONL writer
(
geojsonl_gbxlightweight /geojsonlheavyweight). - Input geometry — provide geometry as WKB (binary) or WKT (text), with the CRS in
the companion
*_srid/*_srid_projcolumns. EWKB, EWKT, and GeoJSON-encoded geometry are not accepted. Writing from a DatabricksGEOMETRY/GEOGRAPHYcolumn? Export to WKB first withST_AsBinary(orST_AsTextfor WKT) — see the Schema section below — and avoidST_GeomAsEWKB/ST_AsEWKT/ST_AsGeoJSON.
Options
| Option | Default | Behavior |
|---|---|---|
driverName | required | OGR driver name (e.g. "GeoJSON", "ESRI Shapefile"). Named writers preset this automatically. |
mode | overwrite | overwrite only; append is rejected. |
geometryType | inferred from the data | Override the OGR geometry type. |
layerName | driver default | Output layer name where supported. |
Schema
All the vector writers — the named shapefile_gbx / geojson_gbx / gpkg_gbx /
file_gdb_gbx and this generic vector_gbx — share one column contract: a geometry
column plus its CRS companions.
root
|-- <geom>: binary (WKB) or string (WKT) # the geometry
|-- <geom>_srid: string # REQUIRED — CRS authority code, e.g. "4326" ("0" if unknown)
|-- <geom>_srid_proj: string # optional — PROJ4 string, CRS fallback when srid is "0"
|-- ...any other columns # written as feature attributes
The geometry is the column that has a companion <geom>_srid. <geom>_srid is required —
it supplies the CRS and identifies the geometry. The _srid / _srid_proj columns are CRS
metadata and are not written as fields; every other column becomes a feature attribute.
There are three ways to satisfy this contract — pick whichever matches your data. These
patterns apply to every vector writer (just swap the format name and any preset
driverName).
(a) Point the writer at your columns — geomCol / sridCol / projCol
If your frame already carries geometry + CRS under other names, name them with options — no renaming required:
(df # e.g. columns: the_geom (WKB), epsg, crs_proj, name, population
.write.format("vector_gbx").option("driverName", "GeoJSON")
.option("geomCol", "the_geom") # geometry column (WKB or WKT)
.option("sridCol", "epsg") # REQUIRED — CRS authority-code column
.option("projCol", "crs_proj") # optional — PROJ4 fallback column
.mode("overwrite").save("/Volumes/cat/sch/vol/out"))
sridCol is required; projCol is optional. See Named Vector Formats.
(b) Or coerce to the convention column names
Build the geom_0 / geom_0_srid / geom_0_srid_proj columns the *_gbx readers emit:
from pyspark.sql import functions as F
df.select(
F.col("my_geom_wkb").alias("geom_0"), # geometry as WKB (or WKT)
F.lit("4326").alias("geom_0_srid"), # CRS authority code
F.lit("").alias("geom_0_srid_proj"), # optional PROJ4 fallback
"name", "population", # -> feature attributes
).write.format("vector_gbx").option("driverName", "GeoJSON").mode("overwrite").save("/Volumes/cat/sch/vol/out")
(c) From a Databricks GEOMETRY / GEOGRAPHY column
Native spatial types aren't a writer input directly — export to WKB plus an SRID first with
ST_AsWKB and ST_SRID. Avoid ST_GeomAsEWKB / ST_AsEWKT / ST_AsGeoJSON — extended and
GeoJSON encodings are not accepted.
df.selectExpr(
"ST_AsWKB(my_geom) AS geom_0", # GEOMETRY/GEOGRAPHY -> WKB
"CAST(ST_SRID(my_geom) AS STRING) AS geom_0_srid", # SRID -> string
"'' AS geom_0_srid_proj",
"name", "population", # -> feature attributes
).write.format("vector_gbx").option("driverName", "GeoJSON").mode("overwrite").save("/Volumes/cat/sch/vol/out")
See Databricks Spatial for the full ST function reference.
The written file round-trips with the matching *_gbx reader — reading it back yields
(…attributes, geom_0, geom_0_srid, geom_0_srid_proj).
Output: the file is written with the OGR driver passed via driverName; attribute and
geometry handling follow that driver's conventions.
How it scales
Unlike a single-node pyogrio.write_* call that serializes one file on one machine, the
vector_gbx writer runs as a Spark DataSource V2 two-phase write: each partition is written
concurrently by its executor to a scratch fragment, then the driver merges the
fragments into one output file. The merge is sequential and rename-free, so it is safe on
FUSE-mounted cloud storage (Unity Catalog Volumes, DBFS). Repartition the input to control
write parallelism.
Example
# Generic lightweight vector writer (pyogrio; no JAR)
from databricks.labs.gbx.ds.register import register
register(spark)
src = f"{SAMPLE_DATA_BASE}/nyc/boroughs/nyc_boroughs.geojson"
df = spark.read.format("geojson_gbx").load(src)
out = "/tmp/nyc_boroughs.geojson" # a single named output file
(df.write.format("vector_gbx")
.option("driverName", "GeoJSON")
.mode("overwrite").save(out))
back = spark.read.format("vector_gbx").option("driverName", "GeoJSON").load(out)
assert back.count() == df.count()
Typical pipeline: export a table to a single file
Export a table of vector data to one file — no coalesce needed (the writer merges partitions into a single file on commit):
df = spark.table("main.geo.features") # vector data in a (Delta) table
df.write.format("vector_gbx").option("driverName", "GeoJSON").mode("overwrite").save("/Volumes/main/geo/exports/features.geojson")
Each partition is written concurrently, then merged into one output file. See Benchmarking for light-vs-heavy export figures.