近距离搜索

21

应用程序如何执行附近搜索?例如,用户输入邮政编码,然后应用程序按接近程度列出所有距离20英里以内的企业。

我想在PHP和MySQL中构建类似的功能。这种方法正确吗?

  1. 获取我感兴趣的位置的地址并将其存储在我的数据库中
  2. 使用Google的地理编码服务对所有地址进行地理编码
  3. 编写包含Haversine公式以执行附近搜索和排序的数据库查询

这样可以吗?在第3步中,我将为每个查询计算接近程度。是否最好拥有一个PROXIMITY表,列出每个企业与几个参考位置之间的距离?


1
另请参见精细的http://www.movable-type.co.uk/scripts/latlong.html#cosine-law - Arjan
3个回答

13
如果有足够的记录需要提高速度,这里有一种事先建立索引的方法。
定义一个大约每边20英里的网格条形箱。将每个店铺的记录与相应的箱号存储在一起。在搜索时,计算所有与搜索点20英里半径内的箱相交的编号。然后检索任何这些箱中的店铺,并像以前一样继续进行操作。

13

我们使用这个来计算成千上万的点。如果你在SQL中执行此操作,对纬度和经度列建立索引非常重要。我们尝试在 SQL 2008 中使用空间索引进行此操作,但实际上并没有看到预期的性能提升。但是,如果您想计算距离某个邮政编码一定距离内的点,请考虑使用邮政编码的质心或多边形表示。

Haversine公式是一个很好的起点。

我们没有在现场计算距离时遇到性能问题,但对于一些应用程序,我们会提前计算距离,因为我们已知点的位置,并且将有数百万条记录。

SELECT
        [DistanceRadius]=
        69.09 *
        DEGREES(
          ACOS(
            SIN( RADIANS(latitude) )*SIN( RADIANS(@ziplat) ) 
           +
            COS( RADIANS(latitude) )*COS( RADIANS(@ziplat) ) 
           *
            COS( RADIANS(longitude - (@ziplon)) )
          )
        )
        ,*
        FROM
            table

    ) sub
WHERE
    sub.DistanceRadius < @radius

2
我们需要对大约1200个地点进行操作。我会实时使用Haversine公式进行计算,但根据您的应用程序,将其存储在PHP中可能比存储在SQL中更好。(我们的实现是在.NET中,所以效果可能有所不同)
事实上,我们实现方式最大的缺点是,直到最近,每次计算都必须在数据层上进行计算,这非常缓慢(当我说缓慢时,我的意思是非瞬间性需要一秒左右的时间),但这是因为它必须基于提供的邮政编码计算所有1200个位置的距离。
根据您选择的路线,有办法加速许多距离的计算,通过查看经度和纬度并删除预定义范围外的部分(例如,如果您正在查看所有地址在20英里内,则可以计算一个经度范围,所有地址必须落在其中才能相距20英里)。如果需要,这可以加快查询速度。
我们曾考虑将所有可能的组合存储在数据库中。实际上,这听起来可能是一个大的数据存储,但在整体范围内并不算。通过索引,它可以非常快速,并且您不必担心算法优化等问题。我们决定反对这种方法,因为我们在C#中有该方程式,它允许我们缓存必要的信息以在业务层中执行所有计算。其中任何一个都可以很好地运行,只是取决于您的个人偏好。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接