Lor*_*ssi 7 php mysql geospatial geo laravel-eloquent
我正在使用Laravel 5.5构建一个php web应用程序,我需要显示按用户指定位置的距离排序的地点列表(例如商店).这些地方将存储在MySQL数据库中,并应作为Eloquent ORM模型实例进行检索.
做了一些研究我发现了很多关于这个主题的帖子和问题(提出了不同的解决方案),但是,由于对数据库和地理定位/地理空间分析的经验很少,他们大多困惑我,我想知道要采用什么方法和什么是这种情况下的最佳做法.
我读过的大多数答案都建议在SQL查询中使用半字形公式或余弦的球面定律,这看起来像(从这个答案中取得的例子):
$sf = 3.14159 / 180; // scaling factor
$sql = "SELECT * FROM table
WHERE lon BETWEEN '$minLon' AND '$maxLon'
AND lat BETWEEN '$minLat' AND '$maxLat'
ORDER BY ACOS(SIN(lat*$sf)*SIN($lat*$sf) + COS(lat*$sf)*COS($lat*$sf)*COS((lon-$lon)*$sf))";
Run Code Online (Sandbox Code Playgroud)
这篇文章指出,在短距离内,假设地球平坦并计算一个简单的欧氏距离是一个很好的近似,并且比使用半正式公式更快.
由于我一次只需要对一个城市内的地点进行排序,这似乎是一个很好的解决方案.
但是,大多数这些帖子和SO答案都有几年的历史了,我想知道现在(MySQL 5.7)是否有更好的解决方案.
例如,这些都不岗位使用任何的MySQL的"空间分析功能",喜欢ST_Distance_Sphere和ST_Distance这似乎是完全用于这一目的.
是否有任何理由(例如,性能,精度)不使用这些函数而不是在查询中编写公式?(我不知道这些函数内部使用了哪种算法)
我也不知道应该如何存储每个地方的坐标.大多数的我看到假定坐标的实例将被存储在单独的lat,lon列作为双打或FLOAT(10,6)(如在该示例中由谷歌),但也MySQL的POINT数据类型似乎是适当用于存储地理坐标.
这两种方法的优点和缺点是什么?
如何使用索引来加速这些查询?例如,我读过"空间索引",但我认为它们只能用于限制结果MBRContains(),而不是按距离实际排序结果.
那么,我应该如何存储地点的坐标以及如何查询它们按距离排序?
除了ST_Distance_Sphere之外,5.7不会为表带来任何额外的内容.(SPATIAL已经实施.)
对于"数千"点,您拥有的代码可能是最好的.包括
INDEX(lat, lng),
INDEX(lng, lat)
Run Code Online (Sandbox Code Playgroud)
除非你伸展数千英里(公里),否则我不会担心地球的曲率.即便如此,代码和该功能应该足够好.
不要使用FLOAT(m,n),仅限使用FLOAT.下面的链接给出了可用的精度FLOAT和其他表示.
如果你有这么多点,你无法完全缓存表及其索引(数百万点),你可以使用它,它使用一些技巧来避免像上述解决方案那样冗长的扫描.由于PARTITION限制,lat/lng表示为缩放整数.(但这很容易在输入/输出中进行转换.)地球的曲率,极点和日期线都被处理掉了.
| 归档时间: |
|
| 查看次数: |
797 次 |
| 最近记录: |