PHP 半径搜索
PHP Radius Search
我将构建一个应用程序,用户可以在其中查看其位置周围预定义半径内的兴趣点。
我的第一个想法是将所有 POI 的纬度和经度存储在数据库中,并通过 SQL 将用户位置与 POI 的位置进行比较。
问题是我认为的性能。如果有数以千计的 POI 和数以千计的用户请求及其位置,这将不会很经济,或者这对今天的服务器来说没有问题吗?
我的下一个方法是将地图划分为象限,并且只观察周围的象限。
tl;博士:
总而言之我要找的是:
- 一种进行半径搜索的方法
- 最多为其他用户缓存结果
- 缓存将在注册新的 POI 时更新。
如果您对如何实现类似的东西有任何想法,请告诉我。
谢谢
法比安
我认为您正在寻找的是 Harversine formula,它可以让您找到球体(在本例中为地球)中两点之间的距离。使用 SQL 的实现将是这样的:
ACOS (
SIN(RADIANS($latitude)) *
SIN(RADIANS(T.latitude))+
COS(RADIANS($latitude)) *
COS(RADIANS(T.latitude))*
COS(RADIANS($longitude-T.longitud)))*6378.137 AS distance
将此添加到您的查询的 select 将 return 一个名为距离的列计算(以公里为单位)距离点($latitude,$longitude)有多远,通常是用户,从(T.latitude,T.longitude), 通常是 table.
的元素
如果您想过滤并且不显示超过一定距离的元素,您可以设置如下条件:
HAVING distance<$radius
我想您正在使用 MySQL,如果是这种情况,您必须使用 HAVING
而不是 WHERE
来对计算列(距离)设置条件。
一个完整的查询示例如下:
SELECT T.*, ACOS (
SIN(RADIANS($latitude)) *
SIN(RADIANS(T.latitude))+
COS(RADIANS($latitude)) *
COS(RADIANS(T.latitude))*
COS(RADIANS($longitude-T.longitud)))*6378.137 AS distance
FROM your_table as T
HAVING distance < $radius
ORDER BY distance LIMIT $limit
如果您想进一步优化性能,请为查询添加一个限制,例如,您将拥有 10 个最近的地点。
也请花点时间考虑一下 Spatial data types,因为它们是专门为此类工作而制作的。
请注意,我不建议您将 php 变量直接插入到查询中,这确实不安全,我这样做只是为了举例。
希望对您有所帮助。
我将构建一个应用程序,用户可以在其中查看其位置周围预定义半径内的兴趣点。
我的第一个想法是将所有 POI 的纬度和经度存储在数据库中,并通过 SQL 将用户位置与 POI 的位置进行比较。
问题是我认为的性能。如果有数以千计的 POI 和数以千计的用户请求及其位置,这将不会很经济,或者这对今天的服务器来说没有问题吗?
我的下一个方法是将地图划分为象限,并且只观察周围的象限。
tl;博士:
总而言之我要找的是:
- 一种进行半径搜索的方法
- 最多为其他用户缓存结果
- 缓存将在注册新的 POI 时更新。
如果您对如何实现类似的东西有任何想法,请告诉我。
谢谢
法比安
我认为您正在寻找的是 Harversine formula,它可以让您找到球体(在本例中为地球)中两点之间的距离。使用 SQL 的实现将是这样的:
ACOS (
SIN(RADIANS($latitude)) *
SIN(RADIANS(T.latitude))+
COS(RADIANS($latitude)) *
COS(RADIANS(T.latitude))*
COS(RADIANS($longitude-T.longitud)))*6378.137 AS distance
将此添加到您的查询的 select 将 return 一个名为距离的列计算(以公里为单位)距离点($latitude,$longitude)有多远,通常是用户,从(T.latitude,T.longitude), 通常是 table.
的元素如果您想过滤并且不显示超过一定距离的元素,您可以设置如下条件:
HAVING distance<$radius
我想您正在使用 MySQL,如果是这种情况,您必须使用 HAVING
而不是 WHERE
来对计算列(距离)设置条件。
一个完整的查询示例如下:
SELECT T.*, ACOS (
SIN(RADIANS($latitude)) *
SIN(RADIANS(T.latitude))+
COS(RADIANS($latitude)) *
COS(RADIANS(T.latitude))*
COS(RADIANS($longitude-T.longitud)))*6378.137 AS distance
FROM your_table as T
HAVING distance < $radius
ORDER BY distance LIMIT $limit
如果您想进一步优化性能,请为查询添加一个限制,例如,您将拥有 10 个最近的地点。
也请花点时间考虑一下 Spatial data types,因为它们是专门为此类工作而制作的。
请注意,我不建议您将 php 变量直接插入到查询中,这确实不安全,我这样做只是为了举例。
希望对您有所帮助。