Server-Side Geocoding and Caching

Google Maps API provides geocoding services to convert addresses (“Singapore 208539”) into geographic coordinates (1.311403, 103.85662). There are two approaches:

  • Client-side geocoding, which uses JavaScript API to send requests and receive responses.
  • HTTP server-side geocoding, which uses HTTP requests to directly query Google’s servers.

Server-side geocoding has a quota of 2,500 requests per IP per day limited by the Geocoding Web Service. Client-side geocoding is distributed across all users. Whenever possible, client-side geocoding is preferred and it doesn’t overload the server.

However, server-side geocoding and caching is helpful if the application repeatedly looks up the same address. When a geocoding request is processed, the server will first check the cache to see if it was geocoded, and if not, the server will send a request to Google, and cache the result.

In the following we use MySQL database to set up a geocoding cache, and use PHP to process geocoding requests.

Geocoding Cache

The following SQL creates a table mapping address strings to its geographical location.

CREATE TABLE location (
  addr varchar(128) NOT NULL,
  faddr varchar(256) NOT NULL,
  lat double NOT NULL,
  lng double NOT NULL,
  updated_time timestamp NOT NULL default CURRENT_TIMESTAMP,
  PRIMARY KEY  (addr)
);

The field addr is the search key, and faddr represents the formatted address returned from Google’s geocoding service. A simple select query finds the result:

SELECT * FROM location WHERE addr = 'singapore 208539';

Use Google Geocoding Service

The following PHP code retrieves geocodes from Google. It constructs a request URL like

http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=singapore+208539

function google_geocoding($addr)
{
	$url = "http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address=".
		urlencode($addr);
	$json_txt = file_get_contents($url);
	if (! $json_txt)
		return FALSE;
	$json_arr = json_decode($json_txt, TRUE);
	if ($json_arr["status"] != "OK")
		return FALSE;

	$result = $json_arr["results"][0];
	$ret = array(
		"addr" => $addr,
		"faddr" => $result["formatted_address"],
		"lat" => $result["geometry"]["location"]["lat"],	
		"lng" => $result["geometry"]["location"]["lng"]
	);
	return $ret; 
}

Search and Update the Cache

When the application needs the geocode for an address, we do the following:

  • Search the cache for the geocode of the address.
  • If found, return the result.
  • If not, use Google’s geocoding service, and then save and return the result.
function my_geocoding($addr)
{
	$addr = trim(strtolower($addr));
	connect_db();

	// Search the cache
	$query = sprintf("select addr, faddr, lat, lng from location where addr like '%s'",
			mysql_real_escape_string($addr) );
	$result = mysql_query($query);
	if ($result && $ret = mysql_fetch_assoc($result))
		return $ret;

	// Search through Google and update the cache
	$ret = google_geocoding($addr);
	$query = sprintf("replace into location(addr, faddr, lat, lng) values('%s', '%s', %f, %f)",
			mysql_real_escape_string($addr),
			mysql_real_escape_string($ret['faddr']),
			$ret['lat'],
			$ret['lng']
			);
	mysql_query($query);
	return $ret; 
}
function connect_db()
{
	$hostname = '00.00.000.000';	
	$username = $dbname = 'xxxx';
	$password = 'xxxx';
	
	mysql_connect($hostname, $username, $password) or 
		die('Unable to connect to database! Please try again later.');
	mysql_select_db($dbname);
	mysql_set_charset('utf8');
}

To use this code, simple write as below:

$addr = "...";

$result = my_geocoding($addr);
$faddr = $result['faddr'];
$lat = $result['lat'];
$lng = $result['lng'];

There are several rules by the Google Maps API Terms of Service: (1) Geocoding results are only allowed to be used on Google Maps or Earth, and cannot be redistributed. (2) Caching is only allowed for a limited time. Actually, geocoding results may be updated over time.

Comments

comments