mobilitydb
Overview
| Package | Version | Category | License | Language |
|---|---|---|---|---|
mobilitydb | 1.3.0 | GIS | GPL-3.0 | C |
| ID | Extension | Bin | Lib | Load | Create | Trust | Reloc | Schema |
|---|---|---|---|---|---|---|---|---|
| 1650 | mobilitydb | No | Yes | No | Yes | No | Yes | - |
| 1651 | mobilitydb_datagen | No | No | No | Yes | No | Yes | - |
| Related | postgis pgrouting h3_postgis timescaledb postgis_topology postgis_raster postgis_sfcgal postgis_tiger_geocoder address_standardizer |
|---|---|
| Depended By | mobilitydb_datagen |
need another schema
Version
| Type | Repo | Version | PG Ver | Package | Deps |
|---|---|---|---|---|---|
| EXT | PGDG | 1.3.0 | 1817161514 | mobilitydb | postgis |
| DEB | PGDG | 1.3.0 | 1817161514 | postgresql-$v-mobilitydb | - |
Install
You can install mobilitydb directly. First, make sure the PGDG repository is added and enabled:
pig repo add pgdg -u # Add PGDG repo and update cache
Install the extension using pig or apt/yum/dnf:
pig install mobilitydb; # Install for current active PG version
pig ext install -y mobilitydb -v 18 # PG 18
pig ext install -y mobilitydb -v 17 # PG 17
pig ext install -y mobilitydb -v 16 # PG 16
pig ext install -y mobilitydb -v 15 # PG 15
pig ext install -y mobilitydb -v 14 # PG 14
apt install -y postgresql-18-mobilitydb # PG 18
apt install -y postgresql-17-mobilitydb # PG 17
apt install -y postgresql-16-mobilitydb # PG 16
apt install -y postgresql-15-mobilitydb # PG 15
apt install -y postgresql-14-mobilitydb # PG 14
Create Extension:
CREATE EXTENSION mobilitydb CASCADE; -- requires: postgis
Usage
mobilitydb: Temporal and spatio-temporal data management for PostgreSQL
MobilityDB extends PostgreSQL and PostGIS with temporal and spatio-temporal data types, enabling efficient storage, indexing, and querying of moving object data such as vehicle trajectories, sensor readings, and time-varying attributes.
Key Documentation:
- MobilityDB Manual
- Temporal Types
- Temporal Operations
- Spatial-Temporal Types
- Indexing
- MobilityDB Workshop
- API Reference
Getting Started
MobilityDB requires PostGIS. Enable both extensions:
CREATE EXTENSION PostGIS;
CREATE EXTENSION MobilityDB;
Temporal Types
MobilityDB provides temporal variants of base types:
| Temporal Type | Base Type | Description |
|---|---|---|
tbool | boolean | Time-varying boolean |
tint | integer | Time-varying integer |
tfloat | float | Time-varying float |
ttext | text | Time-varying text |
tgeompoint | geometry(Point) | Time-varying geometric point |
tgeogpoint | geography(Point) | Time-varying geographic point |
Temporal Subtypes
Each temporal type can be represented in different subtypes depending on how values change over time:
| Subtype | Description | Example |
|---|---|---|
| Instant | Single value at a single timestamp | '25.5@2025-01-01 08:00' |
| Sequence | Continuous values over a time interval | '[25.5@08:00, 28.1@09:00, 30.0@10:00]' |
| SequenceSet | Set of non-overlapping sequences | '{[25.5@08:00, 28.1@09:00], [30.0@11:00, 31.2@12:00]}' |
Sequences use brackets to indicate inclusive [ or exclusive ( bounds, just like PostgreSQL range types.
Creating Temporal Values
Instant values:
SELECT tfloat '25.5@2025-06-01 08:00:00+00';
SELECT tgeompoint 'SRID=4326;Point(2.3522 48.8566)@2025-06-01 08:00:00+00';
Sequence values (continuous interpolation):
SELECT tfloat '[20.0@2025-06-01 08:00, 25.5@2025-06-01 09:00, 22.0@2025-06-01 10:00]';
Discrete sequences (stepwise interpolation):
SELECT tint 'Interp=Step;[10@2025-06-01 08:00, 20@2025-06-01 09:00, 15@2025-06-01 10:00]';
SequenceSet values:
SELECT tfloat '{[20.0@08:00, 25.5@09:00], [22.0@11:00, 28.0@12:00]}';
Constructing from components:
SELECT tgeompoint_inst(ST_Point(2.3522, 48.8566, 4326), '2025-06-01 08:00+00');
SELECT tgeompoint_seq(ARRAY[
tgeompoint_inst(ST_Point(2.3522, 48.8566, 4326), '2025-06-01 08:00+00'),
tgeompoint_inst(ST_Point(2.2945, 48.8584, 4326), '2025-06-01 08:30+00'),
tgeompoint_inst(ST_Point(2.3364, 48.8606, 4326), '2025-06-01 09:00+00')
]);
Temporal Operations
Extracting values at a specific time:
SELECT valueAtTimestamp(temp, '2025-06-01 08:30:00+00')
FROM (SELECT tfloat '[20.0@08:00, 30.0@09:00]' AS temp) t;
-- Returns 25.0 (linear interpolation)
Restricting to a time period:
SELECT atTime(trip, tstzspan '[2025-06-01 08:00, 2025-06-01 09:00]')
FROM trips;
Getting the time span of a temporal value:
SELECT duration(trip), startTimestamp(trip), endTimestamp(trip)
FROM trips;
Temporal comparisons:
-- Time periods when temperature exceeded 30 degrees
SELECT atValue(temperature, true)
FROM (SELECT tfloat '[20@08:00, 35@09:00, 25@10:00]' #> 30.0 AS temperature) t;
Spatial-Temporal Operations
Trajectory: extract the spatial path as a geometry:
SELECT ST_AsText(trajectory(trip))
FROM trips
WHERE vehicle_id = 42;
Speed calculation:
-- Speed in units per second (m/s for geographic points)
SELECT speed(trip)
FROM trips
WHERE vehicle_id = 42;
Length of trajectory:
SELECT length(trip)
FROM trips
WHERE vehicle_id = 42;
Space-time bounding box (stbox):
-- Get the space-time bounding box
SELECT stbox(trip)
FROM trips;
-- Construct an stbox for querying
SELECT stbox(
ST_MakeEnvelope(2.2, 48.8, 2.4, 48.9, 4326),
tstzspan '[2025-06-01, 2025-06-02]'
);
Spatial restriction: values within an area:
-- Portions of a trip within a polygon
SELECT atGeometry(trip, ST_Buffer(ST_Point(2.35, 48.86, 4326), 0.01))
FROM trips;
Distance between two temporal points:
SELECT distance(t1.trip, t2.trip)
FROM trips t1, trips t2
WHERE t1.vehicle_id = 1 AND t2.vehicle_id = 2;
Nearest approach distance and time:
SELECT nearestApproachDistance(t1.trip, t2.trip),
nearestApproachInstant(t1.trip, t2.trip)
FROM trips t1, trips t2
WHERE t1.vehicle_id = 1 AND t2.vehicle_id = 2;
Indexing
MobilityDB supports GiST and SP-GiST indexes for efficient temporal and spatio-temporal queries.
SP-GiST index for temporal types (time dimension):
CREATE INDEX ON measurements USING spgist(temperature);
GiST index for spatio-temporal types (space + time):
CREATE INDEX ON trips USING gist(trip);
These indexes accelerate bounding box queries, temporal overlap checks, and spatial-temporal intersection:
-- Uses GiST index for space-time filtering
SELECT vehicle_id
FROM trips
WHERE trip && stbox(
ST_MakeEnvelope(2.2, 48.8, 2.4, 48.9, 4326),
tstzspan '[2025-06-01, 2025-06-02]'
);
Example: Vehicle Tracking
A complete example storing and querying vehicle GPS trajectories:
CREATE TABLE vehicles (
vehicle_id INT PRIMARY KEY,
plate TEXT,
type TEXT
);
CREATE TABLE trips (
trip_id BIGSERIAL PRIMARY KEY,
vehicle_id INT REFERENCES vehicles(vehicle_id),
trip tgeompoint,
trip_date DATE
);
CREATE INDEX ON trips USING gist(trip);
-- Insert a trip as a sequence of GPS points
INSERT INTO trips (vehicle_id, trip, trip_date) VALUES (
1,
tgeompoint_seq(ARRAY[
tgeompoint_inst(ST_Point(2.3522, 48.8566, 4326), '2025-06-01 08:00+00'),
tgeompoint_inst(ST_Point(2.2945, 48.8584, 4326), '2025-06-01 08:15+00'),
tgeompoint_inst(ST_Point(2.3364, 48.8606, 4326), '2025-06-01 08:30+00'),
tgeompoint_inst(ST_Point(2.3488, 48.8534, 4326), '2025-06-01 08:45+00')
]),
'2025-06-01'
);
-- Where was vehicle 1 at 08:20?
SELECT valueAtTimestamp(trip, '2025-06-01 08:20+00')
FROM trips WHERE vehicle_id = 1 AND trip_date = '2025-06-01';
-- What was the average speed?
SELECT twAvg(speed(trip))
FROM trips WHERE vehicle_id = 1 AND trip_date = '2025-06-01';
-- Total distance traveled
SELECT length(trip)
FROM trips WHERE vehicle_id = 1 AND trip_date = '2025-06-01';
-- Get the full trajectory as a LineString
SELECT ST_AsGeoJSON(trajectory(trip))
FROM trips WHERE vehicle_id = 1 AND trip_date = '2025-06-01';
Example: Spatio-Temporal Intersection Query
Find all trips that passed through a specific area during a given time window:
-- Define area of interest: a circle around the Eiffel Tower
WITH area AS (
SELECT ST_Buffer(ST_Point(2.2945, 48.8584, 4326)::geography, 500)::geometry AS geom
)
SELECT t.vehicle_id,
t.trip_date,
atGeometry(t.trip, a.geom) AS trip_in_area,
length(atGeometry(t.trip, a.geom)) AS distance_in_area
FROM trips t, area a
WHERE t.trip && stbox(
a.geom,
tstzspan '[2025-06-01 07:00+00, 2025-06-01 10:00+00]'
)
AND eIntersects(t.trip, a.geom)
ORDER BY t.trip_date;
Aggregate Functions
MobilityDB provides temporal aggregates:
-- Time-weighted average of a temporal float
SELECT twAvg(temperature) FROM sensor_data WHERE sensor_id = 1;
-- Merge multiple temporal points into one
SELECT tUnion(trip) FROM trips WHERE vehicle_id = 1 AND trip_date = '2025-06-01';
-- Centroid of a set of temporal points at each timestamp
SELECT tCentroid(trip) FROM trips WHERE trip_date = '2025-06-01';
Feedback
Was this page helpful?
Thanks for the feedback! Please let us know how we can improve.
Sorry to hear that. Please let us know how we can improve.