我正在开发一个应用程序,我需要在其中搜索某个地理区域中是否有某些项目。这些项目及其纬度和经度存储在数据库中,存储在还包含其他信息的表格中。我需要做的基本上是在以某些坐标为中心的圆形区域中搜索数据库中的所有项目。现在我只是进行查询以获取所有数据,然后对每个项目进行一些计算以查看它是否在该区域内(基本上是毕达哥拉斯定理,因为我不需要太多的精度)。已经做过类似事情的人可以就如何优化它提供一些建议吗?也许还有某种缓存系统可以返回之前在一般区域中搜索收集的结果,该区域的精度并不重要,并且将圆移动几公里也不会成为问题。 我使用 MySql 作为数据库,PHP 应该产生我的结果。 预先感谢您:)
编辑 我没有发布代码,因为我不要求具体的代码修改,而是更多地要求一种解决问题的直观方法,某种我可以稍后自己编写的算法 无论如何,这是数据库结构 表间隔
ID Int
Addr Text
Info Text
Area Int
Type Text
Lat Double
Lng Double
Time Datetime
Table Area
ID Int
Name Text
这是 PHP 页面
require("Utils.php");
require("Config.php");
if(!array_key_exists("Lat",$_GET) || !array_key_exists("Lng",$_GET)){
$re = array("error"=>"1");
echo json_encode($re);
exit();
}
$lat = $_GET["Lat"];
$lng = $_GET["Lng"];
$mysqli = get_mysqli();
$query = "SELECT `Interv`.`Addr`,`Interv`.`Info`,`Interv`.`Lat`,`Interv`.`Lng`,`Interv`.`Type`, `Area`.`Name` FROM `Interv` JOIN `Area` ON `Interv`.`Area`=`Area`.`ID` WHERE `Time` > '".date("Y-m-d H:i:s",(time() - Max_Time))."';";
$result = $mysqli->query($query);
if($result->num_rows >0){
$responce = array("Error" => 0 , "Data" => array());
$i = 0;
while($row = $result->fetch_array(MYSQLI_ASSOC)){
if(sqrt(pow($lat-$row["Lat"],2)+pow($lng-$row["Lng"],2)) < Max_Distance){
$responce["Data"][$i] = array("Addr" => $row["Addr"], "Info" => $row["Info"], "Type" => $row["Type"], "Area" => $row["Name"]);
$i++;
}
}
echo json_encode($responce);
$result->close();
}
$mysqli->close();
我想过使用谷歌的 API 来计算距离,但我认为这会完全耗尽服务器带宽,所以我不知道如何解决这个问题.-.
再次感谢
最佳答案
这是一种未经优化且在数学上不正确的地理球面距离计算方法。
您通过选择所有数据并根据毕达哥拉斯计算对其进行过滤来进行暴力破解。
毕达哥拉斯线性距离计算对于地圈数据来说是不准确的,因为地球具有曲率,并且不是平面。更好的近似值是 haversine方法。它的实现可以在所有编程语言中轻松实现。但您甚至不必在您的案例中使用它,因为您的案例可以在数据库级别本身解决,因为大多数现代数据库都支持地理空间数据。
对于 mysql 5.6+,地理空间数据类型和查询是内置的。因此,您可以将所有数据与坐标一起存储,并执行单个查询来查找位于特定圆形范围内的所有点。很好的解释here ,以及官方文档here 。
关于php - 优化地理数据搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44035265/