我希望创建一个GPS坐标的大型数据库,可以通过说“返回所有距离[这个坐标]在n米以内的坐标”进行查询。
我需要尽可能高效,因此循环遍历数据库中的所有坐标并计算坐标是否在n米范围内不是理想的解决方案。
有更简单的解决方案吗?
谢谢
我希望创建一个GPS坐标的大型数据库,可以通过说“返回所有距离[这个坐标]在n米以内的坐标”进行查询。
我需要尽可能高效,因此循环遍历数据库中的所有坐标并计算坐标是否在n米范围内不是理想的解决方案。
有更简单的解决方案吗?
谢谢
GIS数据库(例如带有PostGIS的PostgreSQL)实际上为二维或三维区域搜索提供了数据结构(空间索引)。最简单的是网格索引,然后是不同的搜索树(kd-tree、quad-tree),其中R-tree是最常用的(用于更多维度的广义B-tree)。这些方法似乎是足够的。
基本的网格索引(将空间划分为网格单元,并仅在附近单元中进行搜索)可以轻松实现,并且可以显著减少搜索时间。搜索树稍微难以实现,但是有许多开源实现适用于许多编程语言和DB(如PostGIS或Geopandas等)。通常使用它们解决此类问题会得到回报。
如果您想避免使用GIS扩展,我将this post中的函数适配到了PostgreSQL SQL中:
create or replace function change_in_lat(miles numeric)
returns double precision as $$
with v as (select
3960.0 as earth_radius,
180 / pi() as radians_to_degrees
) select ( miles / earth_radius ) * radians_to_degrees from v;
$$ language sql
returns null on null input;
create or replace function change_in_long(lat numeric, miles numeric)
returns double precision as $$
with v as (select
3960.0 as earth_radius,
pi() / 180 as degrees_to_radians,
180 / pi() as radians_to_degrees
) select (
miles / (earth_radius * cos(lat * degrees_to_radians))
) * radians_to_degrees from v;
$$ language sql
returns null on null input;
使用它们,您可以进行一些周围方块的查询:
--find all "a"s within 25 miles of any "b"
select * from a join b on (
a.gpslat between
b.gpslat - change_in_lat(25) and b.gpslat + change_in_lat(25)
and a.gpslong between
b.gpslong - change_in_long(b.gpslat::numeric, 25)
and b.gpslong + change_in_long(b.gpslat::numeric, 25)
);
如果你经常使用它,我相信将语句之间转换为单个函数会很容易。不过我从未使用过任何实际的“半径内”查询。
对于更复杂的操作,你可能需要像其他答案所说的那样使用GIS扩展。PostGIS很好用,但我发现许多gis特定的函数很难正确使用,除非你利用边界框索引,否则如果数据集足够大,你的空间查询可能需要一天时间。但是,为了获得所有花哨的功能(如以geojson格式输出数据等),复杂性上的权衡绝对是值得的。
我们可以使用Geohash算法。
Geohash的美妙之处在于它的构造方式。简而言之,Geohash是一种网格空间索引类型,其中世界被递归地划分为越来越小的网格,并带有每个附加位。(https://www.mapzen.com/blog/geohashes-and-you/)
你可以在维基百科上找到它的描述(https://en.wikipedia.org/wiki/Geohash)。
我附上了下面的视频以便快速理解。
https://www.youtube.com/watch?v=UaMzra18TD8
https://youtu.be/mx1mMdHBi5Q?t=1955
在下一篇文章中,您可以找到AWS数据库DynamoDB的此类算法的实现。 https://read.acloud.guru/location-based-search-results-with-dynamodb-and-geohash-267727e5d54f 请为James Beswick的文章鼓掌。