Skip to content

API Reference

/

Values

Geometry

SurrealDB stores geospatial data in the geometry type, which follows GeoJSON. The Python SDK has one class for each of the seven kinds of geometry, and each class maps to its SurrealDB kind in both directions. This page documents the constructors, which take their parts as separate arguments, and how geometry reads back.

Import
from surrealdb import (
    GeometryCollection,
    GeometryLine,
    GeometryMultiLine,
    GeometryMultiPoint,
    GeometryMultiPolygon,
    GeometryPoint,
    GeometryPolygon,
)

Source: geometry.py

ClassSurrealDB typeConstructor
GeometryPointgeometry<point>GeometryPoint(longitude, latitude)
GeometryLinegeometry<line>GeometryLine(point1, point2, *more_points)
GeometryPolygongeometry<polygon>GeometryPolygon(exterior_ring, *interior_rings)
GeometryMultiPointgeometry<multipoint>GeometryMultiPoint(*points)
GeometryMultiLinegeometry<multiline>GeometryMultiLine(*lines)
GeometryMultiPolygongeometry<multipolygon>GeometryMultiPolygon(*polygons)
GeometryCollectiongeometry<collection>GeometryCollection(*geometries)

Every constructor takes its parts as separate positional arguments. GeometryLine(start, end) is correct, and GeometryLine([start, end]) raises TypeError. To build a geometry from a list, unpack the list: GeometryLine(*points).

A point gives its longitude first and its latitude second, the same order as GeoJSON.

The Geometry base class is also exported. Use it in an isinstance() check for the first six classes. GeometryCollection is not a subclass of Geometry, and a Geometry itself cannot be sent.

A GeometryPoint is a single position.

Syntax
GeometryPoint(longitude, latitude)

Parameter

Type

Description

longitudefloat

The longitude, or the x coordinate.

latitudefloat

The latitude, or the y coordinate.

The point keeps the two values as its longitude and latitude attributes.

london = GeometryPoint(-0.1278, 51.5074)
print(london.longitude, london.latitude)
Output
-0.1278 51.5074

A GeometryLine is a line through two or more points, in order.

Syntax
GeometryLine(point1, point2, *more_points)

Parameter

Type

Description

point1

,

point2
GeometryPoint

The first two points of the line.

*more_pointsGeometryPoint

Further points, in order.

The points are in the geometry_points attribute, a list[GeometryPoint].

route = GeometryLine(
    GeometryPoint(-0.1278, 51.5074),
    GeometryPoint(-1.8904, 52.4862),
    GeometryPoint(-3.1883, 55.9533),
)
print(len(route.geometry_points))
Output
3

A GeometryPolygon is a polygon made of one outer ring and any number of inner rings, which are holes. A ring is a GeometryLine that is closed: its first and last points are equal, and it has at least four points.

Syntax
GeometryPolygon(exterior_ring, *interior_rings)

Parameter

Type

Description

exterior_ringGeometryLine

The outer boundary.

*interior_ringsGeometryLine

Holes inside the outer boundary.

The rings are in the geometry_lines attribute, outer ring first. A ring that is not closed, or that has fewer than four points, raises InvalidGeometryError.

outer = GeometryLine(
    GeometryPoint(0, 0),
    GeometryPoint(4, 0),
    GeometryPoint(4, 4),
    GeometryPoint(0, 4),
    GeometryPoint(0, 0),
)
hole = GeometryLine(
    GeometryPoint(1, 1),
    GeometryPoint(2, 1),
    GeometryPoint(2, 2),
    GeometryPoint(1, 2),
    GeometryPoint(1, 1),
)
area = GeometryPolygon(outer, hole)
print(len(area.geometry_lines))
Output
2

A GeometryMultiPoint is a group of points.

Syntax
GeometryMultiPoint(*points)

The points are in the geometry_points attribute.

stops = GeometryMultiPoint(
    GeometryPoint(-0.1278, 51.5074),
    GeometryPoint(-3.1883, 55.9533),
)
print(len(stops.geometry_points))
Output
2

A GeometryMultiLine is a group of lines.

Syntax
GeometryMultiLine(*lines)

The lines are in the geometry_lines attribute.

tracks = GeometryMultiLine(
    GeometryLine(GeometryPoint(0, 0), GeometryPoint(1, 1)),
    GeometryLine(GeometryPoint(2, 2), GeometryPoint(3, 3)),
)
print(len(tracks.geometry_lines))
Output
2

A GeometryMultiPolygon is a group of polygons.

Syntax
GeometryMultiPolygon(*polygons)

The polygons are in the geometry_polygons attribute.

square = GeometryLine(
    GeometryPoint(0, 0),
    GeometryPoint(1, 0),
    GeometryPoint(1, 1),
    GeometryPoint(0, 1),
    GeometryPoint(0, 0),
)
farms = GeometryMultiPolygon(GeometryPolygon(square))
print(len(farms.geometry_polygons))
Output
1

A GeometryCollection is a group of geometries of any kind, mixed.

Syntax
GeometryCollection(*geometries)

The geometries are in the geometries attribute.

site = GeometryCollection(
    GeometryPoint(-0.1278, 51.5074),
    GeometryLine(GeometryPoint(0, 0), GeometryPoint(1, 1)),
)
print(len(site.geometries))
Output
2

str() renders a geometry as a SurrealQL literal, for logs and debugging. To use a geometry in a query, pass it as a variable instead.

print(GeometryPoint(-0.1278, 51.5074))
print(GeometryLine(GeometryPoint(0, 0), GeometryPoint(1, 1)))
Output
(-0.1278, 51.5074)
{ type: 'LineString', coordinates: [[0, 0], [1, 1]] }

Every class except GeometryCollection also has these methods:

MethodReturnsDescription
get_coordinates()tuple or listThe GeoJSON coordinates, with each position as a (longitude, latitude) tuple.
parse_coordinates(coordinates)the same classStatic method. Builds a geometry from GeoJSON coordinates.

Two geometries of the same class are equal when their coordinates are equal, and every geometry is hashable.

Store a geometry as a field value, and pass one as a query variable to use it with the geo functions.

from surrealdb import GeometryPoint, RecordID, Surreal

with Surreal("ws://localhost:8000") as db:
    db.signin({"username": "root", "password": "secret"})
    db.use("surrealdb", "docs")

    db.create(RecordID("place", "london"), {
        "location": GeometryPoint(-0.1278, 51.5074),
    })
    db.create(RecordID("place", "edinburgh"), {
        "location": GeometryPoint(-3.1883, 55.9533),
    })

    sql = """
        SELECT VALUE id FROM place
        WHERE geo::distance(location, $here) < 50000
    """
    here = GeometryPoint(-0.1180, 51.5099)
    print(db.query(sql, {"here": here}).first())
Output
[RecordID(table_name=place, record_id='london')]

A geometry reads back as the same class. The coordinates of a point read back as float values, so GeometryPoint(1, 2) reads back as GeometryPoint(longitude=1.0, latitude=2.0), which is still equal to the point that was sent.

Was this page helpful?