postgis-nearest

📁 mmbmf1/geospatial-skills 📅 4 days ago
1
总安装量
1
周安装量
#54269
全站排名
安装命令
npx skills add https://github.com/mmbmf1/geospatial-skills --skill postgis-nearest

Agent 安装分布

amp 1
opencode 1
cursor 1
kimi-cli 1
codex 1
github-copilot 1

Skill 文档

Nearest Feature (KNN / <->)

Use this skill when you need the nearest feature to a point/geometry (e.g., nearest feeder, nearest segment, nearest hub).

PostGIS supports fast nearest-neighbor searches using the KNN operator <-> when a GiST index exists.

When to use

  • “Find the nearest X to this point”
  • “Rank candidates by proximity”
  • “Pick the closest feature per input row”

Core rules

  • KNN <-> works best with GiST indexes on geometry columns
  • <-> orders by distance in the geometry’s coordinate system (SRID units)
  • For meaningful distances, use a projected SRID or geography (meters)
  • Keep queries index-friendly: avoid wrapping the indexed column in transforms inside ORDER BY when possible

Index requirement

CREATE INDEX IF NOT EXISTS features_geom_gix ON features USING gist (geom);

Without this, KNN will not be fast.

Canonical pattern: nearest feature to a single point

-- point is EPSG:4326 here
WITH p AS (
  SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326) AS geom
)
SELECT f.*
FROM features f, p
ORDER BY f.geom <-> p.geom
LIMIT 1;

Nearest N features

WITH p AS (
  SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326) AS geom
)
SELECT f.*
FROM features f, p
ORDER BY f.geom <-> p.geom
LIMIT 10;

Add an exact distance (optional)

Compute the distance separately (don’t replace the KNN order):

WITH p AS (
  SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326) AS geom
)
SELECT
  f.*,
  ST_Distance(f.geom::geography, p.geom::geography) AS distance_m
FROM features f, p
ORDER BY f.geom <-> p.geom
LIMIT 1;

Here:

  • ordering stays fast via KNN
  • distance is computed in meters via geography

Recommended: constrain candidates with ST_DWithin

For large tables, reduce work and avoid weird global matches:

WITH p AS (
  SELECT ST_SetSRID(ST_MakePoint($1, $2), 4326) AS geom
)
SELECT f.*
FROM features f, p
WHERE ST_DWithin(f.geom::geography, p.geom::geography, 5000) -- 5km
ORDER BY f.geom <-> p.geom
LIMIT 1;

Different SRIDs

If your features are stored in a projected/client SRID, build the point in that SRID (or transform once):

WITH p AS (
  SELECT ST_Transform(
    ST_SetSRID(ST_MakePoint($1, $2), 4326),
    $3  -- client_srid
  ) AS geom
)
SELECT f.*
FROM features f, p
ORDER BY f.geom <-> p.geom
LIMIT 1;

Prefer storing and indexing features.geom in the SRID you query most often.

Common mistakes

  • No GiST index (query is slow)
  • Using <-> on EPSG:4326 and assuming the distance is meters
  • Transforming f.geom inside ORDER BY (can kill index usage)
  • Not bounding the search (use ST_DWithin when appropriate)

Summary

  • Use ORDER BY geom <-> point LIMIT 1 for nearest neighbor
  • Ensure GiST index on geom
  • Use geography or projected SRID for real-world distance values
  • Add ST_DWithin to keep searches local and fast