Introduction
Geocoding is the process of converting an address (like "1600 Amphitheatre Parkway, Mountain View, CA
") into geographic coordinates (like latitude 37.423021 and longitude -122.083739).
The Google maps API is a great API to get location information like this. But the fuzzy address parameter (basically an array separated by commas) can be quite cumbersome if you want to get a detailed location but want to use as little information as possible. For instance, to avoid typos. Because when spelling a street name or city wrong, there will be zero results (so much for the fuzzy).
Background
Nowadays, the housenumber (streetnumber) and postalcode (zipcode) combination is sufficient enough in a lot of countries getting a unique specific location of an address without explicitly specifying the street and city.
It would be nice if the Address
parameter of the Google maps APIs would support this, but unfortunately that is not the case. Most parts of the address
parameter are mandatory as for instance a street name and/or city. So you need at least a street name and a city to get proper results.
In the processing of trial and error, I tried to use wildcards in the address parameter but that is also not supported.
But here's a solution.
Using the Code
Unfortunately, it can't be done in 1 call. To get an appropriate address
by housenumber
and postalcode
, we have basically to perform 3 calls:
- Supply the
postcode
and get the LatLng
coordinates - Supply these
LatLng
coordinates and get the streetname
- Finally, combine
streetname
and housenumber
to get the exact coordinates of the address
And this is how we do it (this is JavaScript, don't forget to include the Google maps API in a script
tag):
var geocoder = new google.maps.Geocoder();
var housenumber = 1;
var postalcode = 5171 KW;
geocoder.geocode({ 'componentRestrictions':
{ 'postalCode': postalcode }, region: "nl" }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var result = results[0].geometry.location;
}
This will supply the proper LatLng
coordinates. Notice we don't use the address
parameter at this point yet. Usually we use componentRestrictions
in combination with the address
parameter, for instance to restrict results to a country only. But you can use componentRestrictions
only and it has an important advantage: instead of the fuzzy address parameter, you can explicitly tell it to use the postalcode
(and only that) as a search parameter.
Notice that I also used the region
parameter to restrict results to a specific country only. You could also use the country
parameter instead of the region
:
geocoder.geocode({ 'componentRestrictions':
{ 'postalCode': postalcode, 'country': "nl" }}
But the downside of this is that it always returns a result, even when the postalcode
doesn't exist. It returns some kind of global result of the country instead. We don't want that, we want zero results and you should therefore use region
.
The next step is to get the global address information of this particular LatLng
combination:
var geocoder = new google.maps.Geocoder();
var housenumber = 1;
var postalcode = 5171 KW;
geocoder.geocode({ 'componentRestrictions':
{ 'postalCode': postalcode }, region: "nl" }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var result = results[0].geometry.location;
geocoder.geocode({ latLng: results[0].geometry.location }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var address;
if (results[0].types[0] == 'street_address' && results[0].address_components[1]) {
address = results[0].address_components[1].long_name + " " + housenumber;
}
else if (results[0].types[0] == 'route') {
address = results[0].address_components[0].long_name + " " + housenumber;
}
}
}
Now you will have the proper streetname
. The next step is to combine the streetname
and housenumber
and get the exact geocode:
var geocoder = new google.maps.Geocoder();
var housenumber = 1;
var postalcode = 5171 KW;
var exactAdresLocation;
geocoder.geocode({ 'componentRestrictions':
{ 'postalCode': postalcode }, region: "nl" }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var result = results[0].geometry.location;
geocoder.geocode({ latLng: results[0].geometry.location }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var streetname;
if (results[0].types[0] == 'street_address' && results[0].address_components[1]) {
streetname = results[0].address_components[1].long_name ;
}
else if (results[0].types[0] == 'route') {
streetname = results[0].address_components[0].long_name;
}
var address = streetname + " " + housenumber;
geocoder.geocode({ 'address': address, 'componentRestrictions':
{ 'postalCode': postalcode }, region: "nl" }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
exactAdresLocation = results[0].geometry.location;
}
});
}
}
That's it. It took me a while to figure out. I'll hope it will help someone.