yggdrasil.data.types.geo¶
geo ¶
:class:GeoPointType — canonical struct of (lat, lon) float64.
A two-column nested struct used by curated tables that carry a location reference. The contract:
lat: float64in WGS84 degrees, range[-90, 90].lon: float64in WGS84 degrees, range[-180, 180].
Both columns are non-nullable inside the struct — when a row has
no location, mark the whole struct nullable via the parent
:class:Field (geo_point("position", nullable=True)). Mixing
NULL with one valid coordinate is meaningless.
Why a struct (not two flat columns)¶
Two flat columns (lat, lon) are fine when the location is a
top-level attribute of the row. Switch to GeoPointType when:
- the row carries multiple locations (
origin,destination) and flat naming would proliferate (origin_lat/origin_lon/destination_lat/destination_lonreads worse than twoGeoPointcolumns), - a downstream sink (Arrow, Parquet, JSON, GeoJSON encoder, frontend
map plugin) speaks the
{"lat": …, "lon": …}shape natively, - a list-of-points column (
points: list<struct<lat, lon, …>>) is the shape — see :func:geo_pointbelow.
For flat-column curated rows the column-naming convention from
ygg-curated-views (lat: float64, lon: float64 at the top
level) still applies — they're equivalent payloads, pick whichever
reads better at the call site.
Implementation¶
:data:GEO_POINT_TYPE is a pre-built :class:StructType instance
the rest of the codebase imports as a singleton; building a fresh
StructType per call would defeat the cast-registry's exact-match
fast path. :func:geo_point is the corresponding Field factory
so callers don't have to repeat the field args (nullable,
metadata, tags).
geo_point ¶
geo_point(
name: str,
*,
nullable: bool = True,
comment: Optional[str] = None,
metadata: Optional[Mapping[Union[bytes, str], Any]] = None,
tags: Optional[Mapping[Union[bytes, str], Any]] = None
) -> "Field"
Build a :class:Field of the canonical :data:GEO_POINT_TYPE.
nullable flips on the struct — the inner lat / lon
children stay non-nullable so partial-coordinate rows (one of
the two NULL) can't slip through.
Example::
from yggdrasil.data import Field, Schema, geo_point
ORIGIN_DESTINATION_SCHEMA = Schema.from_fields([
Field("trip_id", DataType.string(), nullable=False),
geo_point("origin", comment="Pickup point, WGS84."),
geo_point("destination", comment="Drop-off point, WGS84."),
])
is_geo_point_type ¶
Return True when value is the canonical GeoPoint shape.
Matches a :class:StructType with exactly the two children
lat: float64 + lon: float64 (any nullability, any extra
metadata). Useful for downstream code that wants to emit a
GeoJSON / map-plugin representation for these and only these
struct columns.