【问题标题】:Finding ZIP codes/coordinates for listings within a radius of another ZIP code using Long/Lat coordinates [closed]使用长/纬度坐标查找另一个邮政编码半径内的列表的邮政编码/坐标[关闭]
【发布时间】:2014-08-31 08:18:51
【问题描述】:

我想查找邮政编码任意半径范围内的所有列表。例如距离 90210 10 英里,距离 00603 100 英里,等等。

如果我的查询是“距离 90210 10 英里”,我想返回这 10 英里半径内的所有列表。列表也是邮政编码,所以我基本上想找到这 10 英里半径内的所有其他邮政编码。

我想一旦我收集了半径中的所有邮政编码,然后我将它们添加到一个数组中,然后使用 SQL 查找该数组中包含邮政编码的所有列表。但是,我不确定这是否是最好的方法。

我曾尝试进行研究,但对我来说变得非常复杂;我认为这可能与大圆有关。我也一直在 http://williams.best.vwh.net/avform.htm 研究航空公式,但仍然无法解决任何问题。

我有一个邮政编码数据库,其中包含所有邮政编码的经度和纬度,以及城市和州信息。这是我需要的足够信息。我想我只需要知道数学;我不想使用 API。

关于如何计算这样的半径,我完全迷失了。

【问题讨论】:

  • 这样的事情怎么样? zipcodedistanceapi.redline13.com/API#radius
  • 我不想使用 API,我有一个包含所有必要信息的数据库,我只是不知道实现我想要的数学。
  • 所以,基础是:获取邮政编码的经度和纬度,以英里为单位计算距离,然后计算该距离的半径,然后搜索数据库中的所有邮政编码计算出的半径内的 lat 和 lon 再次转换为 lat 和 lon。
  • “以英里为单位计算距离”是什么?半径不需要计算,例如设置100 英里。

标签: php mysql dictionary math zipcode


【解决方案1】:

您可以通过调用以下api获取与输入的邮政编码对应的所有邮政编码列表:-

$zipcode=90210;
$distancekm=10;

$curl = curl_init();
   curl_setopt_array($curl, array( 
   CURLOPT_RETURNTRANSFER => 1,

   CURLOPT_URL => 
       'http://zipcodedistanceapi.redline13.com/rest/2odywUYrQJOEEO0vJdlcH5Qd8Lf6EGKG4YfBTd2JXQoCFo7pBsBiysvGdLNSsyzw/radius.json/'.$zipcode.'/'.$distancekm.'/mile'));

   $result = curl_exec($curl);

   $decoded_result = json_decode($result, true);

$decoded_result 会返回距离邮政编码 90210 近 10 英里的所有邮政编码。

希望这对你有帮助。

【讨论】:

  • 谢谢,理想情况下我不想使用 API,但如果我不知道如何用 mysql 来做,我可能别无选择。所以这将返回一个数组中的邮政编码列表,然后我会只过滤那些邮政编码的结果?使用 IN()?
  • 是的,您可以使用 IN() 来完成。 $zipcode='你要搜索的邮编';像:-“选择 * from table_name where $zipcode IN($zipcodes)”; $zipcodes 是所有返回的邮政编码的数组。
【解决方案2】:

您提到了 3 个不同的问题:

  • “英里”和“地理坐标”没有直接转换。您可能听说过,地球并不平坦 :-),这意味着赤道和洛杉矶纬度的 1º 经度将以英里为单位有不同的谷值。您链接的公式是spherical law of cosines 的应用程序,它允许您以更快的近似值转换经度和纬度差异

  • 假设您可能有很多地址,您的第二个问题是常规 MySQL 索引(B-Trees)对于通过最近坐标进行过滤可能非常低效。一些数据库供应商(Oracle、Postgress)具有“GIS 扩展”,允许对地理坐标执行快速查找。虽然 MySQL 具有这些特定的数据类型和功能,但早期版本的范围和性能非常有限。最新版本(5.6 和 5.7)在某种程度上改进了这一点,您可以在此处查看使用 MySQL 过滤坐标附近位置的示例:

    http://mysqlserverteam.com/mysql-5-7-and-gis-an-example/

    它涉及使用边界框进行过滤,这使得 MySQL 功能更容易。 上一个链接在分步指南中包含所有公式和查询。

  • 您打算执行点搜索,然后执行第二个查询以检索每个找到的位置的信息。这在网络带宽方面是不必要的并且可能效率低下,您可以通过执行自连接(在表中加入搜索特定邮政编码并搜索地理上接近的记录)在单个查询中完成所有操作。

这是另一个关于 GIS 和 MySQL 的链接:http://www.slideshare.net/henrikingo/spatial-functions-in-mysql-56-mariadb-55-postgis-20-and-others

【讨论】:

  • 那么如何为每个列表做一个表连接,添加一个额外的与邮政编码距离的列?然后过滤所有距离
  • 当然它会简化计算(这是一种常见的非规范化/优化技巧),但要注意,因为该表的大小将是 n^2 记录 - 如果您打算存储 20 个 zip,则可以维护,但是可能不是一百万。
  • 大约有 250,000 个列表。我想创建按最近对它们进行排序并按半径过滤它们的能力。这种方式可行吗?
  • 那是一个辅助的62500000000行表!我建议您按照我在答案解决方案中的建议动态计算它。
【解决方案3】:

也许这个 Java 项目可以提供帮助。该项目以公里为单位进行配置。您可以在 CityDAO.java 中修改这些

public List<City> findCityInRange(GeoPoint geoPoint, double distance) {
    List<City> cities = new ArrayList<City>();
    QueryBuilder queryBuilder = geoDistanceQuery("geoPoint")
            .point(geoPoint.getLat(), geoPoint.getLon())
            //.distance(distance, DistanceUnit.KILOMETERS) original
            .distance(distance, DistanceUnit.MILES)
            .optimizeBbox("memory")
            .geoDistance(GeoDistance.ARC);

    SearchRequestBuilder builder = esClient.getClient()
            .prepareSearch(INDEX)
            .setTypes("city")
            .setSearchType(SearchType.QUERY_THEN_FETCH)
            .setScroll(new TimeValue(60000))
            .setSize(100).setExplain(true)
            .setPostFilter(queryBuilder)
            .addSort(SortBuilders.geoDistanceSort("geoPoint")
                    .order(SortOrder.ASC)
                    .point(geoPoint.getLat(), geoPoint.getLon())
                    //.unit(DistanceUnit.KILOMETERS)); Original
                    .unit(DistanceUnit.MILES));

    SearchResponse response = builder
            .execute()
            .actionGet();


    SearchHit[] hits = response.getHits().getHits();

    scroll:
    while (true) {

        for (SearchHit hit : hits) {
            Map<String, Object> result = hit.getSource();
            cities.add(mapper.convertValue(result, City.class));
        }

        response = esClient.getClient().prepareSearchScroll(response.getScrollId()).setScroll(new TimeValue(60000)).execute().actionGet();
        if (response.getHits().getHits().length == 0) {
            break scroll;
        }
    }

    return cities;
}

“LocationFinder\src\main\resources\json\cities.json”文件包含比利时的所有城市。如果需要,您也可以删除或创建条目。只要您不更改名称和/或结构,就不需要更改代码。

请务必阅读自述文件https://github.com/GlennVanSchil/LocationFinder

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-20
    • 1970-01-01
    • 2019-04-16
    • 2013-04-05
    • 2010-10-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多