我正在尝试使用PostGIS解决找到n个最近邻居的问题:
起点:
问题: 在由id表示的表geoname中找到给定Point的n(例如5)最近邻居(geoname.geonameid。
可能的解决方案:
受http://www.bostongis.com/PrinterFriendly.aspx?content_name=postgis_nearest_neighbor的启发,我尝试了以下查询:
"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"
处理时间:约60秒
还尝试了一种基于EXPAND的方法:
"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"
处理时间:约120秒
预期的应用程序是某种自动完成。因此,任何花费超过> 1s的方法都不适用。通常可以使用PostGIS实现<1s的响应时间吗?
答案 0 :(得分:44)
现在,自PostGIS 2.0以来,已有几种可用的几何类型的KNN索引。 这将为您提供最接近的5条记录,忽略远离“您的位置......”的距离。
SELECT *
FROM your_table
ORDER BY your_table.geom <-> "your location..."
LIMIT 5;
请参阅<->
运算符in PostgreSQL manual。
答案 1 :(得分:7)
正如我认为你在列表中回答的那样,单位是度数,因此你几乎在st_dwithin中以300度搜索整个世界。
如果您的数据集很大,那么您无法在投影的基于米的投影中工作(更快且更少CPU计算),您应该考虑使用地理数据类型。然后你可以使用st_dwithin和米。
你应该更快地创建一个新的表格,其中几何图形转换为地理位置。
但是为了测试它,你可以在飞行中投射:
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 尼克拉斯