{"id":1587,"date":"2013-05-30T20:24:38","date_gmt":"2013-05-30T20:24:38","guid":{"rendered":"http:\/\/www.sitekickr.com\/blog\/?p=1587"},"modified":"2013-08-27T01:47:00","modified_gmt":"2013-08-27T01:47:00","slug":"batch-geocoding-coldfusion-google-maps-api-javascript","status":"publish","type":"post","link":"https:\/\/www.sitekickr.com\/blog\/batch-geocoding-coldfusion-google-maps-api-javascript\/","title":{"rendered":"Batch Geocoding with ColdFusion, Google Maps API and JavaScript"},"content":{"rendered":"<p>Okay, that title was a mouthful, but I wanted to accurately describe how decided to Geocode thousands of locations for a client of mine.<\/p>\n<p>Google, awesome as they are, have offered a ridiculously simple API to consume:<\/p>\n<p><code>http:\/\/maps.googleapis.com\/maps\/api\/geocode\/json?address=<em>theaddress<\/em>&amp;sensor=false<\/code><\/p>\n<p>But, they naturally have rate limits, and even if they didn&#39;t, I&#39;d feel more comfortable using their API responsibly. It is completely free after all.<\/p>\n<p>So, I decided to write a ColdFusion script which does the following:<\/p>\n<ol>\n<li>Pulls a single location record from a database<\/li>\n<li>Sends the address from the record to the Google API<\/li>\n<li>If the API returns a result, store it in the database<\/li>\n<li>Otherwise, indicate that geocoding failed, so we don&#39;t attempt to geocode this record again.<\/li>\n<\/ol>\n<p>Since we&#39;re only doing one record at a time, we&#39;ll have to set this up to run automatically at a specified interval. This is where the JavaScript part comes in.<\/p>\n<p>I could have setup a cron job without much effort, but knowing me, I&#39;d forget to remove it once geocoding is complete. So, I decided to open up my web browsers console, and drop in the following:<\/p>\n<p><code><span class=\"objectBox objectBox-text \" role=\"presentation\">setInterval(function() { <br \/>\n\t&nbsp;&nbsp;&nbsp; $.ajax({<br \/>\n\t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; url: &#39;http:\/\/www.mysite.com\/do-the-geocode-thing.cfm&#39;, <br \/>\n\t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; success: function(data) { <\/span><span class=\"objectBox objectBox-text \" role=\"presentation\"><br \/>\n\t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; console.log(data); <br \/>\n\t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br \/>\n\t&nbsp;&nbsp;&nbsp; }) <br \/>\n\t}, 35000);<\/span><\/code><\/p>\n<p><span class=\"objectBox objectBox-text \" role=\"presentation\">The 35 second interval is enough to comply with Google&#39;s 2,500 query\/day limit.<\/span> The ColdFusion script follows below:<\/p>\n<p>&nbsp;<\/p>\n<p><code>&lt;cfquery name=&quot;locations&quot;&gt;<br \/>\n\t&nbsp;&nbsp;&nbsp; SELECT id, address<br \/>\n\t&nbsp;&nbsp;&nbsp; FROM locations<br \/>\n\t&nbsp;&nbsp;&nbsp; WHERE latitude = 0<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp; AND failed_geocode = 0<br \/>\n\t&nbsp;&nbsp;&nbsp; LIMIT 1<br \/>\n\t&lt;\/cfquery&gt;<\/p>\n<p>\t&lt;cfloop query=&quot;locations&quot;&gt;<br \/>\n\t&nbsp;&nbsp;&nbsp; &lt;cfset api = &quot;http:\/\/maps.googleapis.com\/maps\/api\/geocode\/json?address=#URLEncodedFormat(address)#&amp;sensor=false&quot;&gt;<br \/>\n\t&nbsp;&nbsp;&nbsp; <br \/>\n\t&nbsp;&nbsp;&nbsp; &lt;cfhttp url=&quot;#api#&quot;&gt;&lt;\/cfhttp&gt;<br \/>\n\t&nbsp;&nbsp;&nbsp; <br \/>\n\t&nbsp;&nbsp;&nbsp; &lt;cfset response = DeserializeJSON(cfhttp.FileContent)&gt;<br \/>\n\t&nbsp;&nbsp;&nbsp; <br \/>\n\t&nbsp;&nbsp;&nbsp; <br \/>\n\t&nbsp;&nbsp;&nbsp; &lt;cftry&gt;<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;cfset point = response[&quot;results&quot;][1][&quot;geometry&quot;][&quot;location&quot;]&gt;<\/p>\n<p>\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;cfoutput&gt;#SerializeJSON(point)#&lt;\/cfoutput&gt;<\/p>\n<p>\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;cfquery&gt;<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; UPDATE locations<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; SET latitude = &lt;cfqueryparam value=&quot;#point.lat#&quot;&gt;,<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; longitude = &lt;cfqueryparam value=&quot;#point.lng#&quot;&gt;<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; WHERE id = &lt;cfqueryparam value=&quot;#locations.id#&quot;&gt;<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;\/cfquery&gt;<\/p>\n<p>\t&nbsp;&nbsp;&nbsp; &lt;cfcatch&gt;<\/p>\n<p>\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;cfquery&gt;<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; UPDATE locations<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; SET failed_geocode = 1<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; WHERE id = &lt;cfqueryparam value=&quot;#locations.id#&quot;&gt;<br \/>\n\t&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;\/cfquery&gt;<\/p>\n<p>\t&nbsp;&nbsp;&nbsp; &lt;\/cfcatch&gt;<br \/>\n\t&nbsp;&nbsp;&nbsp; &lt;\/cftry&gt;<br \/>\n\t&lt;\/cfloop&gt;<\/code><\/p>\n","protected":false},"excerpt":{"rendered":"<p>A simple method to GeoCode a large number of addresses with ColdFusion while respecting Google&#8217;s query limit.<\/p>\n","protected":false},"author":1,"featured_media":1589,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"amp_status":""},"categories":[34,238,1],"tags":[202],"_links":{"self":[{"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/posts\/1587"}],"collection":[{"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/comments?post=1587"}],"version-history":[{"count":8,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/posts\/1587\/revisions"}],"predecessor-version":[{"id":1685,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/posts\/1587\/revisions\/1685"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/media\/1589"}],"wp:attachment":[{"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/media?parent=1587"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/categories?post=1587"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sitekickr.com\/blog\/wp-json\/wp\/v2\/tags?post=1587"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}