Google's Geocoder returns wrong country, ignoring the region hint

我怕爱的太早我们不能终老 提交于 2019-11-28 04:08:53
Daniel Vassallo

UPDATE: This answer may not be the best approach anymore. See the comments below the answer for more details.


In addition to what Pekka already suggested, you may want to concatenate ', UK' to your address, as in the following example:

<!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>

Screenshot:

I find that this is very reliable. On the other hand, the following example shows that neither the region parameter, nor the bounds parameter, are having any effect in this case:

<!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>

The following code will get the first matching address in the UK without the need to modify the address.

  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;
                    }
                }
            }
        }
    });
Yenya

Use componentRestrictions attribute:

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

The correct way of doing this is by providing componentRestrictions

For example:

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

According to the docs, the region parameter seems to set a bias only (instead of a real limit to that region). I guess when the API doesn't find the exact address in the UK place, it will expand it search no matter what region you enter.

I've fared pretty well in the past with specifying the country code in the address (in addition to the region). I haven't had much experience with identical place names in different countries yet, though. Still, it's worth a shot. Try

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

it should return no address (Instead of the US Boston), and

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

Should return the Boston in the UK because that actually has a Main Street.

Update:

How to restrict Geocoder to return locations only from one country or maybe from a certain lat lng range?

You can set a bounds parameter. See here

You would have to calculate a UK-sized rectangle for that, of course.

I found problems with putting ",UK", setting the region to UK and setting bounds. However, doing ALL THREE seems to fix it for me. Here's a snippet:-

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.....
Ankit Adlakha

I tried with the following:

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

And its working for me for particular region (US country).

I always found this to be pretty easy to filter through since the results can vary and the region doesn't seem to work.

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

I prefer a hybrid approach.

  1. Use componentRestrictions to severely limit to country first.
  2. If that doesn't yield enough results, search more broadly (and re-introduce bias if necessary)

    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 }

I find that for a lot of ambiguous queries, the US always takes precedence in Google, even if you try to tell it where to look. You can look at the response and perhaps ignore it if output country=US?

That is the main reason I stopped using Google Geocoder a while ago and started building my own two years ago.

https://geocode.xyz/Boston,%20UK will always return the UK location. You can make extra sure by adding region=UK: https://geocode.xyz/Boston,%20UK?region=UK

I have Created Border All Around Uk and check if my Lat and Lng are in the Range. For 3 k addresses I have around 10 up to 20 addresses in US. I just Ignore them(I can do that in my case) I use lat and lng for creating multi markers on static map with auto zoom. I will share my Solution maybe this will be help for someone. Also I'm Happy to hear different Solutions for my case.

    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;
    }

For the united kingdom, you have to use GB for region. UK is not the ISO country code!

I had to filter results to a country myself today. I found out that the two character country code in componentRestrictions:country: does not work. But the full country name does.

This is the full_name in the address_components from a result.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!