Using ST_AsMVT

Matthew Shaw shawmat.sl6 at gmail.com
Sun Jul 6 05:40:43 PDT 2025


I'm struggling to understand how to use ST_AsMVT.   It doesn't exist as a
true function, but this PSQL command shows that it does exist as an "agg"

\df *st_asmvt*

  Schema |     Name     | Result data type |
                  Argument data types
           | Type
--------+--------------+------------------+----------------------------------------------------------------------------------------------------------------------+------
 public | st_asmvt     | bytea            | anyelement

          | agg
 public | st_asmvt     | bytea            | anyelement, text

          | agg
 public | st_asmvt     | bytea            | anyelement, text, integer

         | agg
 public | st_asmvt     | bytea            | anyelement, text, integer, text

         | agg
 public | st_asmvt     | bytea            | anyelement, text, integer,
text, text
               | agg
 public | st_asmvtgeom | geometry         | geom geometry, bounds box2d,
extent integer DEFAULT 4096, buffer integer DEFAULT 256, clip_geom boolean
DEFAULT true | func

The MapLibre Martin server relies on one MVT being assembled from all the
geometries in the underlying. The following query successfully finds 93
geometries for tile .../highways/12/1019/671

SELECT
      ST_AsMVTGeom(geom,
          ST_TileEnvelope(11,1019, 671),
          4096, 64, true) AS geom,
 class
    FROM openstreetmap.highway

    WHERE geom && ST_Transform(ST_TileEnvelope(11,1019, 671), 4326)

But as soon as I try to invoke ST_AsMVT, it errors:

select ST_AsMVT(tile, 'highways'::text, 4096, 'geom'::text, array['class'])
from
    (SELECT
      ST_AsMVTGeom(geom,
          ST_TileEnvelope(11,1019, 671),
          4096, 64, true) AS geom,
 class
    FROM openstreetmap.highway
    WHERE geom && ST_Transform(ST_TileEnvelope(11,1019, 671), 4326)) as tile


ERROR: function st_asmvt(record, text, integer, text, text[]) does not
exist LINE 3: select ST_AsMVT(tile, 'highways'::text, 4096, 'geom'::text,
... ^ HINT: No function matches the given name and argument types. You
might need to add explicit type casts.

All I'm doing is following the pattern in the Maplibre Martin
documentation.  It suggests defining functions like this:

CREATE OR REPLACE
FUNCTION function_zxy_query(z integer, x integer, y integer)
RETURNS bytea AS $$
DECLARE
mvt bytea;
BEGIN
SELECT INTO mvt *ST_AsMVT*(tile, 'function_zxy_query', 4096, 'geom') FROM (
SELECT
ST_AsMVTGeom(
ST_Transform(ST_CurveToLine(geom), 3857),
ST_TileEnvelope(z, x, y),
4096, 64, true) AS geom
FROM table_source
WHERE geom && ST_Transform(ST_TileEnvelope(z, x, y), 4326)
) as tile WHERE geom IS NOT NULL;
RETURN mvt;
END
$$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;


I spent time checking my PostGIS installation.  ST_AsMVT doesnt exist as a
function on any of the PostGIS server installations I have access to, so
it's not obviously a defective installation.

I'd welcome some help fixing this.  Yes, Martin can (and does) work with
direct reference to tables, but functions are necessary to manage what's
included at various zoom levels.

Thanks

*Matthew Shaw*
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osgeo.org/pipermail/postgis-users/attachments/20250706/816ca7e9/attachment.htm>


More information about the postgis-users mailing list