【问题标题】:Google's Geocoder returns wrong country, ignoring the region hint谷歌的地理编码器返回错误的国家,忽略地区提示
【发布时间】:2011-02-08 11:29:06
【问题描述】:

我正在使用 Google 的地理编码器来查找给定地址的 lat lng 坐标。

    var geocoder = new google.maps.Geocoder();
    geocoder.geocode(
    {
        'address':  address,
        'region':   'uk'
    }, function(results, status) {
        if(status == google.maps.GeocoderStatus.OK) {
            lat: results[0].geometry.location.lat(),
            lng: results[0].geometry.location.lng()
    });

address 变量取自输入字段。

我想搜索仅在英国的位置。我认为指定'region': 'uk' 应该就足够了,但事实并非如此。当我输入“波士顿”时,它会在美国找到波士顿,而我想要在英国找到波士顿。

如何限制地理编码器仅返回来自一个国家或可能来自某个 lat lng 范围的位置?

谢谢

【问题讨论】:

    标签: javascript google-maps geolocation gps geocode


    【解决方案1】:

    以下代码无需修改地址即可得到英国境内第一个匹配的地址。

      var geocoder = new google.maps.Geocoder();
      geocoder.geocode(
      {
        'address':  address,
        'region':   'uk'
      }, function(results, status) {
        if(status == google.maps.GeocoderStatus.OK) {
            for (var i=0; i<results.length; i++) {
                for (var j=0; j<results[i].address_components.length; j++) {
                   if ($.inArray("country", results[i].address_components[j].types) >= 0) {
                        if (results[i].address_components[j].short_name == "GB") {
                            return_address = results[i].formatted_address;
                            return_lat = results[i].geometry.location.lat();
                            return_lng = results[i].geometry.location.lng();
                            ...
                            return;
                        }
                    }
                }
            }
        });
    

    【讨论】:

    • 我认为你是唯一一个以 API 的预期使用方式回答这个问题的人。按照记录设置偏差 - 然后实际检查结果以查看是否存在首选匹配。
    • 是的,这是最好的答案!添加“, UK”或“, US”实际上会产生搜索街道地址而不是位置的意外效果;最好假设您可以返回多个结果并搜索以找到您想要的区域中的一个。
    • 无论我做什么,我对“Clevedon”的搜索都只会返回一个结果。即使将偏差设置为 NZ,它也会从英国返回一个结果,在地址中添加“, NZ”会返回来自新西兰的结果,但我无法同时获得两个结果并使用这种扫描技术将其缩减为一个我想要。
    • 第三个 for 循环是干什么用的?我看不到在任何地方使用k,并且types.lengthshort name 值无关。
    • 你在 2012 年 2 月能做的最好的,但现在你应该使用 componentRestrictions,它是在 2013 年 7 月添加到 JavaScript API 中的。
    【解决方案2】:

    使用componentRestrictions属性:

    geocoder.geocode({'address': request.term, componentRestrictions: {country: 'GB'}}
    

    【讨论】:

    • 这可以让“Clevedon”返回 Zn 而不是英格兰的城镇,但是当我搜索一个不存在的地址时,它会返回整个国家的结果(根据规范)而不是零结果。
    • 返回整个国家是预期的:“如果未找到匹配项,则地理编码器将返回与过滤器本身匹配的结果。” -- developers.google.com/maps/documentation/geocoding/…
    • 我尝试过的最佳解决方案,返回相对结果且仅适用于指定国家!在其他函数中提到了 componentRestrictions,但在 Geocoder 中没有记录。
    • 文档指出国家字段“匹配国家名称或两个字母的 ISO 3166-1 国家代码”。英国的 ISO 代码是 GB,但英国也可以使用。
    【解决方案3】:

    更新:这个答案可能不再是最好的方法了。有关详细信息,请参阅答案下方的 cmets。


    除了Pekka already suggested,您可能还想将', UK' 连接到您的address,如下例所示:

    <!DOCTYPE html>
    <html> 
    <head> 
       <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> 
       <title>Google Maps Geocoding only in UK Demo</title> 
       <script src="http://maps.google.com/maps/api/js?sensor=false" 
               type="text/javascript"></script> 
    </head> 
    <body> 
       <div id="map" style="width: 400px; height: 300px"></div> 
    
       <script type="text/javascript"> 
    
       var mapOptions = { 
          mapTypeId: google.maps.MapTypeId.TERRAIN,
          center: new google.maps.LatLng(54.00, -3.00),
          zoom: 5
       };
    
       var map = new google.maps.Map(document.getElementById("map"), mapOptions);
       var geocoder = new google.maps.Geocoder();
    
       var address = 'Boston';
    
       geocoder.geocode({
          'address': address + ', UK'
       }, 
       function(results, status) {
          if(status == google.maps.GeocoderStatus.OK) {
             new google.maps.Marker({
                position:results[0].geometry.location,
                map: map
             });
          }
       });
    
       </script> 
    </body> 
    </html>
    

    截图:

    我发现这是非常可靠的。另一方面,以下示例表明,region 参数和 bounds 参数在这种情况下都不起作用:

    <!DOCTYPE html>
    <html> 
    <head> 
       <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> 
       <title>Google Maps Geocoding only in UK Demo with Bounds</title> 
       <script src="http://maps.google.com/maps/api/js?sensor=false" 
               type="text/javascript"></script> 
    </head> 
    <body> 
       <div id="map" style="width: 500px; height: 300px"></div> 
    
       <script type="text/javascript"> 
    
       var mapOptions = { 
          mapTypeId: google.maps.MapTypeId.TERRAIN,
          center: new google.maps.LatLng(50.00, -33.00),
          zoom: 3
       };
    
       var map = new google.maps.Map(document.getElementById("map"), mapOptions);   
       var geocoder = new google.maps.Geocoder();
    
       // Define north-east and south-west points of UK
       var ne = new google.maps.LatLng(60.00, 3.00);
       var sw = new google.maps.LatLng(49.00, -13.00);
    
       // Define bounding box for drawing
       var boundingBoxPoints = [
          ne, new google.maps.LatLng(ne.lat(), sw.lng()),
          sw, new google.maps.LatLng(sw.lat(), ne.lng()), ne
       ];
    
       // Draw bounding box on map    
       new google.maps.Polyline({
          path: boundingBoxPoints,
          strokeColor: '#FF0000',
          strokeOpacity: 1.0,
          strokeWeight: 2,
          map: map
       });
    
       // Geocode and place marker on map
       geocoder.geocode({
          'address': 'Boston',
          'region':  'uk',
          'bounds':  new google.maps.LatLngBounds(sw, ne)
       }, 
       function(results, status) {
          if(status == google.maps.GeocoderStatus.OK) {
             new google.maps.Marker({
                position:results[0].geometry.location,
                map: map
             });
          }
       });
    
       </script> 
    </body> 
    </html>
    

    【讨论】:

    • 这就是我所说的“肮脏修复”,但我认为我必须这样做:/
    • @6bytes: 可能是hack,但我还是要找一个不能用的案例。
    • 我们在这里发现了一个相当大的错误 :) 我希望 Google 知道并尽快修复它。
    • 您可能还想在groups.google.com/group/google-maps-api/topics 的公共 Google Maps API 帮助论坛中发布此内容(如果您还没有这样做 :-))。
    • @Fraser :答案是很久以前发布的......据我记得,当时的结果不包括“其他”地方,所以如果你搜索“波士顿”,你会得到一个代表“波士顿,美国”的结果集,结果以“反向精度顺序”排序(因此,第一个结果通常是街道级精度,第二个是城市级精度,然后是国家级, 等等)。从那时起事情可能已经发生了变化,所以如果我有时间我会尝试再次验证这一点,并根据需要更新我的答案。感谢您的 cmets!
    【解决方案4】:

    这样做的正确方法是提供componentRestrictions

    例如:

    var request = {
        address: address,
        componentRestrictions: {
            country: 'UK'
        }
    }
    geocoder.geocode(request, function(results, status){
        //...
    });
    

    【讨论】:

      【解决方案5】:

      根据docs,区域参数似乎只设置了一个偏差(而不是对该区域的实际限制)。我猜当 API 在英国找不到确切的地址时,无论您输入哪个地区,它都会扩大搜索范围。

      过去我在地址中指定国家/地区代码(除了地区)做得很好。 不过,我还没有太多在不同国家使用相同地名的经验。尽管如此,还是值得一试。试试

      'address': '78 Austin Street, Boston, UK'
      

      它应该返回无地址(而不是美国波士顿),并且

      'address': '78 Main Street, Boston, UK'
      

      应该返回英国的波士顿,因为那里实际上有一条主街。

      更新:

      如何限制地理编码器仅返回来自一个国家或可能来自某个 lat lng 范围的位置?

      您可以设置bounds 参数。见here

      当然,您必须为此计算一个英国大小的矩形。

      【讨论】:

      • 输入“波士顿”返回美国,输入“波士顿,英国”返回英国。如果我从欧洲连接,为什么首先返回美国位置?我不能强迫我的用户输入国家代码:(
      • @Pekka,我尝试地理编码78 Austin Street, Boston, UK 只是出于好奇,但它返回了一些靠近曼彻斯特的随机“奥斯汀大道”。谷歌地图链接:maps.google.com/…
      • @Daniel 这很奇怪。当我在 Google 地图中输入该地址时,我得到一个明确的“找不到地址”。 (地理编码结果应该带有极低的accuracy 值。)
      • @6bytes:我认为如果有歧义,Google 倾向于选择最受欢迎的城市(这在 Stack Overflow 上讨论过一次:看起来它选择了人口最多的城市)。显然region 参数应该返回英国城市,但显然它还不可靠。我目前知道的唯一可靠方法是将“,英国”连接到您的地址。如果用户添加了国家代码并且您添加了两次英国部分,这也不会受到影响(即使您可能想要检查)。
      • 你救了我!谢谢。
      【解决方案6】:

      我发现在输入“,UK”、将区域设置为 UK 和设置边界时存在问题。但是,做所有三件事似乎可以为我解决问题。这是一个sn-p:-

      var sw = new google.maps.LatLng(50.064192, -9.711914)
      var ne = new google.maps.LatLng(61.015725, 3.691406)
      var viewport = new google.maps.LatLngBounds(sw, ne);
      
      geocoder.geocode({ 'address': postcode + ', UK', 'region': 'UK', "bounds": viewport }, function (results, status) {
              if (status == google.maps.GeocoderStatus.OK) {
      .....etc.....
      

      【讨论】:

      • 我已经测试了“边界”:视口本身,并且可以确认它可以正常工作。 'region': 'UK' 也是如此,因此我选择了后者。谢谢。
      • 不,事实上我错了。我需要这三个!对于不相信我的人,请尝试使用“fsdfsdafsa”地址,您会发现事实上它确实返回了美国的地址,即使地区设置为英国也是如此。我现在已将“,英国”附加到我的“地址”中。谢谢。
      【解决方案7】:

      我尝试了以下方法:

      geocoder.geocode( {'address':request.term + ', USA'}
      

      它适用于特定地区(美国)。

      【讨论】:

        【解决方案8】:

        我总是发现这很容易过滤,因为结果可能会有所不同,而且该区域似乎不起作用。

        response( $.map( results, function( item ) {
         if (item.formatted_address.indexOf("GB") != -1) {
            return {
              latitude: item.geometry.location.lat(),
              longitude: item.geometry.location.lng()
            }
          }
        }
        

        【讨论】:

          【解决方案9】:

          对于英国,您必须使用 GB 表示地区。英国不是 ISO 国家代码!

          【讨论】:

          【解决方案10】:

          我更喜欢混合方法

          1. 首先使用 componentRestrictions 严格限制到国家/地区。
          2. 如果这不能产生足够的结果,请进行更广泛的搜索(并在必要时重新引入偏见)

            function MyGeocoder(address,region)
            {
                geocoder = new google.maps.Geocoder();
                geocoder.geocode({ 'address': address, 'componentRestrictions': { 'country': region } }, function (r, s) {
                    if (r.length < 10) geocoder.geocode({ 'address': address /* could also bias here */ }, function (r2, s2) {
                        for (var j = 0; j < r2.length; j++) r.push(r2[j]);
                        DoSomethingWithResults(r);
                    });
                    else DoSomethingWithResults(r);
                });
            }
            function DoSomethingWithResults(r) { // Remove Duplicates var d = {}; r = r.filter(function (e) { var h = e.formatted_address.valueOf(); var isDup = d[h]; d[h] = true; return !isDup; });

            // Do something with results }

          【讨论】:

            【解决方案11】:

            我发现对于很多模棱两可的查询,美国总是优先在 Google 中,即使你试图告诉它在哪里查找。如果输出 country=US,您可以查看响应并忽略它?

            这就是我不久前停止使用 Google Geocoder 并在两年前开始自己构建的主要原因。

            https://geocode.xyz/Boston,%20UK 将始终返回英国位置。您可以通过添加 region=UK 来更加确定:https://geocode.xyz/Boston,%20UK?region=UK

            【讨论】:

              【解决方案12】:

              我已经在英国各地创建了边界,并检查我的纬度和经度是否在范围内。对于 3 k 地址,我在美国有大约 10 到 20 个地址。我只是忽略它们(在我的情况下我可以这样做)我使用 lat 和 lng 在具有自动缩放功能的静态地图上创建多个标记。我将分享我的解决方案,也许这会对某人有所帮助。我也很高兴听到针对我的案例的不同解决方案。

                  private static string ReturnLatandLng(string GeocodeApiKey, string address)
                  {
                      string latlng = "";
              
                      Geocoder geocoder = new Geocoder(GeocodeApiKey);
              
                      var locations = geocoder.Geocode(address);
              
                      foreach (var item in locations)
                      {
              
                          double longitude = item.LatLng.Longitude;
                          double latitude = item.LatLng.Latitude;
                          double borderSouthLatitude = 49.895878;
                          double borderNorthLatitude = 62.000000;
                          double borderWestLongitude = -8.207676;
                          double borderEastLongitude = 2.000000;
              
                          //Check If Geocoded Address is inside of the UK
                          if (( (borderWestLongitude < longitude) && (longitude < borderEastLongitude) ) && ( (borderSouthLatitude < latitude) && (latitude < borderNorthLatitude) ) )
                          {
                              latlng = item.LatLng.ToString();
                          }
                          else
                          {
                              latlng = "";
                              Console.WriteLine("GEOCODED ADDRESS IS NOT LOCATED IN UK ADDRESSES LIST. DELETING MARKER FROM MAP.....");
                          }
                      }
                      return latlng;
                  }
              

              【讨论】:

                【解决方案13】:

                我今天必须自己将结果过滤到一个国家/地区。我发现 componentRestrictions:country: 中的两个字符国家代码不起作用。但是完整的国家名称。

                这是结果中 address_components 中的全名。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-07-12
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2013-11-28
                  相关资源
                  最近更新 更多