sql - espaciales - ¿Buscar n vecinos más cercanos para un punto dado usando PostGIS?
st_geometry (2)
Ahora, desde PostGIS 2.0, hay un índice KNN para los tipos de geometría disponibles. Esto le da a los 5 registros más cercanos sin tener en cuenta qué tan lejos están de "su ubicación ...".
SELECT *
FROM your_table
ORDER BY your_table.geom <-> "your location..."
LIMIT 5;
Ver el operador <->
en el manual de PostgreSQL .
Estoy tratando de resolver el problema de encontrar a los n vecinos más cercanos utilizando PostGIS:
Punto de partida:
- Tabla geoname con geonames (de geonames.org) que contiene latitud / longitud (WSG-84)
- Se agregó un geom GeometryColumn con srid = 4326 y datatype = POINT
- Geom rellenado con valores: ACTUALIZAR geoname SET geom = ST_SetSRID (ST_Point (longitud, latitud), 4326);
- Se creó el índice GIST para geom (CREATE INDEX geom_index ON geoname USANDO GIST (geom);) / Geom_index agrupado: CLUSTER geom_index ON geoname;
- Se creó el índice PRIMREE KEY UNIQUE BTREE para geonameid
Problema: encuentre n (por ejemplo, 5) vecinos más cercanos para un Punto dado en la tabla geoname representado por id (geoname.geonameid).
Solución posible:
Inspirado en http://www.bostongis.com/PrinterFriendly.aspx?content_name=postgis_nearest_neighbor , probé la siguiente consulta:
"SELECT start.asciiname, ende.asciiname, distance_sphere(start.geom, ende.geom) as distance " +
"FROM geoname As start, geoname As ende WHERE start.geonameid = 2950159 AND start.geonameid <> ende.geonameid " +
"AND ST_DWithin(start.geom, ende.geom, 300) order by distance limit 5"
Tiempo de procesamiento: alrededor de 60 s
También probé un enfoque basado en EXPANDIR:
"SELECT start.asciiname, ende.asciiname, distance_sphere(start.geom, ende.geom) as distance " +
"FROM geoname As start, geoname As ende WHERE start.geonameid = 2950159 AND start.geonameid <> ende.geonameid AND expand(start.geom, 300) && ende.geom " +
"order by distance limit 5"
Tiempo de procesamiento: unos 120s
La aplicación prevista es algún tipo de autocompletar. Por lo tanto, cualquier enfoque que tome más de 1 año no es aplicable. ¿Es generalmente posible lograr un tiempo de respuesta de <1s con PostGIS?
Como creo que te respondieron en la lista, la unidad está en grados, por lo que casi estás buscando en todo el mundo con 300 grados en total.
Si su conjunto de datos es tan grande que no puede trabajar en una proyección basada en medidor proyectado en su lugar (cálculos mucho más rápidos y menos intensivos en CPU) debería considerar usar el tipo de geografía. Entonces puedes usar st_dwithin con el medidor.
Para hacer las cosas más rápidas, debería crear una nueva tabla con la geometría convertida a geografía.
Pero solo para probarlo puedes lanzar sobre la marcha:
SELECT start.asciiname, ende.asciiname,
ST_Distance(start.geom::geography, ende.geom::geography) as distance
FROM geoname As start, geoname As ende
WHERE start.geonameid = 2950159 AND start.geonameid <> ende.geonameid AND
ST_DWithin(start.geom::geography, ende.geom::geography, 300)
order by distance
limit 5;
HTH Nicklas