All Products
Search
Document Center

PolarDB:ST_MapMatching

Last Updated:Mar 28, 2026

Snaps a geometry or trajectory to the nearest matching roads in a workspace and returns the matched road geometry.

Syntax

geometry ST_MapMatching(text wsname, geometry geom, text options);
geometry ST_MapMatching(text wsname, trajectory traj, text options);

Parameters

ParameterDescription
wsnameThe name of the workspace.
geomThe geometric object that you want to match against the road network data in the workspace.
trajThe trajectory that you want to match against the road network data in the workspace.
optionsA JSON string containing matching algorithm and tuning parameters.

Return values

Returns a geometry consisting of a sequence of road segments that corresponds to the input geometry or trajectory.

Description

  • You can enter geometric line objects or trajectory objects for matching.

  • If you specify a trajectory object, the geometry objects in the trajectory object are matched and new matched geometry objects are returned. The attribute information of the trajectory objects is not returned.

  • The function returns new geometric objects that consist of a sequence of segments that corresponds to the input geometric objects.

Prerequisites

Before you begin, ensure that you have:

  • A road network table with the required schema (fid, source, target, cost, geom)

  • A workspace created from the road network table using st_createworkspace

Match geometry to a road network

This example sets up a road network, creates a workspace, and runs ST_MapMatching to snap a GPS trace to the nearest roads.

Step 1: Create the road network table

CREATE TABLE network (
    fid    bigint,                              -- Unique identifier for the road segment
    source bigint,                              -- Start node of the road segment
    target bigint,                              -- End node of the road segment
    cost   double precision,                    -- Road weight value (not currently used)
    geom   public.geometry(LineString, 4326)    -- Geometry of the road segment
);

Step 2: Insert road segment data

INSERT INTO network(fid, source, target, cost, geom) VALUES(1,  1,  2,  1, st_geomfromtext('LINESTRING(2 1,2 0)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(2,  2,  1,  1, st_geomfromtext('LINESTRING(2 0,2 1)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(3,  3,  1,  1, st_geomfromtext('LINESTRING(3 1,2 1)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(4,  4,  3,  1, st_geomfromtext('LINESTRING(4 1,3 1)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(5,  1,  5,  1, st_geomfromtext('LINESTRING(2 1,2 2)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(6,  5,  1,  1, st_geomfromtext('LINESTRING(2 2,2 1)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(7,  3,  6,  1, st_geomfromtext('LINESTRING(3 1,3 2)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(8,  7,  8,  1, st_geomfromtext('LINESTRING(0 2,1 2)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(9,  8,  7,  1, st_geomfromtext('LINESTRING(1 2,0 2)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(10, 5,  8,  3, st_geomfromtext('LINESTRING(2 2,1 2)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(11, 8,  5,  3, st_geomfromtext('LINESTRING(1 2,2 2)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(12, 6,  5,  1, st_geomfromtext('LINESTRING(3 2,2 2)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(13, 5,  6,  1, st_geomfromtext('LINESTRING(2 2,3 2)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(14, 6,  9,  1, st_geomfromtext('LINESTRING(3 2,4 2)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(15, 9,  6,  1, st_geomfromtext('LINESTRING(4 2,3 2)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(16, 10, 5,  1, st_geomfromtext('LINESTRING(2 3,2 2)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(17, 5,  10, 1, st_geomfromtext('LINESTRING(2 2,2 3)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(18, 6,  11, 1, st_geomfromtext('LINESTRING(3 2,3 3)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(19, 10, 11, 1, st_geomfromtext('LINESTRING(2 3,3 3)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(20, 11, 12, 1, st_geomfromtext('LINESTRING(3 3,4 3)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(21, 13, 10, 1, st_geomfromtext('LINESTRING(2 4,2 3)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(22, 10, 13, 1, st_geomfromtext('LINESTRING(2 3,2 4)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(23, 9,  12, 1, st_geomfromtext('LINESTRING(4 2,4 3)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(24, 12, 9,  1, st_geomfromtext('LINESTRING(4 3,4 2)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(25, 9,  4,  1, st_geomfromtext('LINESTRING(4 2,4 1)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(26, 4,  9,  1, st_geomfromtext('LINESTRING(4 1,4 2)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(27, 14, 15, 1, st_geomfromtext('LINESTRING(0.5 3.5,2 3.5)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(28, 15, 14, 1, st_geomfromtext('LINESTRING(2 3.5,0.5 3.5)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(29, 16, 17, 1, st_geomfromtext('LINESTRING(3.5 4,3.5 2.3)'));
INSERT INTO network(fid, source, target, cost, geom) VALUES(30, 17, 16, 1, st_geomfromtext('LINESTRING(3.5 2.3,3.5 4)'));

Step 3: Create a workspace

Build the road network topology from the network table.

SELECT st_createworkspace('mm_ws_test1', 'select fid, source, target, geom from network');

Step 4: Create a trajectory table

CREATE TABLE traj(id int, geom geometry(linestring, 4326));
INSERT INTO traj(id, geom)
VALUES(1, st_geomfromtext('LINESTRING(4.15 1.6,3.47 0.92,2.4 0.92,2.14 1.53,2.14 2.57,2.49 2.98)'));

Step 5: Run map matching

Pass a GPS trace as a LineString and the matching options as a JSON string.

SELECT ST_AsText(ST_MapMatching('mm_ws_test', ST_GeomFromText('LINESTRING(4.15 1.6,3.47 0.92,2.4 0.92,2.14 1.53,2.14 2.57,2.49 2.98)'), '{"algorithm":"stmatch","k":4,"r":0.25,"e":0.5}'::text));

Expected output:

geom
----------------------------------------------
 LINESTRING(4 1.6,4 1,3 1,2 1,2 2,2 3,2.49 3)
(1 row)

The result is a LineString that follows the road network, with the input GPS points snapped to the nearest matching road segments.

image