我有一个数据库,我填充了我选择的特定位置。对于每个位置,我将提供经度和纬度。
我想获取我网站访问者的geoIP(在maxmind.com等数据库中匹配的给定IP的经度和纬度)。使用geoIP,我想从我的位置数据库表中找到最接近访问者的位置。
我花了很多时间试图找出如何以有效的方式实现这一目标;我不希望这个过程对每个访客来说都很昂贵。这个过程不必精确,只需要足够精确。如果它给用户萨克拉门托而不是旧金山,这本来更正确,那没关系。只要误差程度足够小,就不会打扰大多数用户。什么是不可能的是,如果算法给出一个完全关闭的位置并且与它们的位置无关,比如芝加哥(当他们住在加利福尼亚时)。
所以说,有什么解决方案?
以下是我的一些想法:
使用毕达哥拉斯定理来找出平面中两点之间的距离。唯一的问题是地球不在平面坐标系上,而是在球面坐标系上。所以,我需要一种方法将地理位置数据(long。和lat。)转换为X和Y坐标。然后我可以运行一个SQL查询,找到最短distance
的记录,该记录使用以下公式计算:sqrt(abs(locationX - geoIpX)^2 + abs(locationY - geoIpY)^2)
我不确定这是不是一个合理的解决方案。如果是,那么请为我平滑粗糙的边缘,这样我就可以实现它。
找出使用经度和纬度差异的算法。例如,首先找到与geoIP经度具有最接近经度的位置,然后找到该集合中具有与geoIP纬度最近纬度的位置。刚刚描述的算法的唯一问题是误差范围可能巨大。例如,假设加利福尼亚州的一个城市距离geoIP是3度经度,但加拿大经度的城市距离是2度,将会发生这样的经线将用于找到最近的纬度,这可能只是加拿大的城市。尽管加拿大的纬度比加利福尼亚州的纬度多得多,但用户将获得与加拿大而不是加利福尼亚州相关的数据,这将是一个太大的错误。但是,也许这个算法有一些修改可以解决这个问题吗?
感谢阅读。所有解决方案和帮助都非常感谢! :)
答案 0 :(得分:1)
您可以使用Haversine公式。 http://www.scribd.com/doc/2569355/Geo-Distance-Search-with-MySQL
为了优化搜索,您可以提供最大,最小坐标 对于max min coords,您可以使用服务器端函数进行处理,也可以使用存储过程来计算这些函数 max min coords的示例:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^([^/]+)/?$ /$1.php [L,NC]
Mysql + php:
$minLng = $lng-($distance/(abs(cos(rad2deg($lat))*69)));
$maxLng = $lng+($distance/(abs(cos(rad2deg($lat))*69)));
$minLat = $lat-($distance/69);
$maxLat = $lat+($distance/69);
然后在having子句中使用此distance_to_destination 或使用where in where子句
缩小搜索范围
$select = "3956 * 2 * ASIN(SQRT(POWER(SIN((initial.pin_lat - " . $destination.lat . ") * pi()/180 / 2), 2) +COS(" .
"initial.pin_lat * pi()/180) * COS(" . $destination.lat . " * pi()/180) *POWER(SIN((" .
"initial.pin_lng - " . $destination.long . ") * pi()/180 / 2),2))) as distance_to_destination";
答案 1 :(得分:0)
你想要Haversine formula。由于该计算涉及三角函数,因此它往往有点昂贵。
您可以考虑将部分数据复制到支持内置地理位置搜索的配套技术。 MySQL在这种类型的搜索方面并不擅长,但其他一些工具也是如此。
例如,Sphinx Search支持地理距离搜索:
MySQL确实支持spatial indexes,但只支持MyISAM表。避免使用MyISAM表的原因有很多。
答案 2 :(得分:0)
mysql和其他数据库一样好。你可以使用空间索引。我写了一个php类,用怪物曲线解决空间索引。你可以在phpclasses下载我的希尔伯特曲线包。它也使用mercantor投影,我使用它非常成功。其他数据库有本机支持,但您可以在几个小时内自己完成。