Mass geocoding using API

Introduction

At last the long promised method of mass geocoding the wappler way no scripts involved.
As this is basically a reply to a post from @mimuk i will base this tutorial around his data table structures.

Sorry about general quality, having to do this on laptop as main machine dead so few rough edges due to lack of software and using a singe screen!

Hope i have not missed any stages

We will be using the google API but the principal will be the same should you wish to use another such as photon.

Considerations

One if the issues we need to workaround is to control the rate of API calls to within the allowable rate for google. To do this we will use a script which only geocodes one address and use the scheduler to “refresh” this until all are geocoded.

Methodology

So the basic function will be:
Query the database for an entry in need to geocodiing (in this case isgeocoded = Null)
Concatenate the address fields into a full address and set in a variable
call the API script
If successful set the geo info otherwise set as geo failed
Repeat until all done

Data Structures

So the data structures we will be using are:

Address:
image

AddressGeoCode
image

geoaddressid is a foreign key to primary key addressid

The server Action

Firstly we create a server action (i have called get_non_geocoded) The server action

This will have 3 stages

image

Database Connection

Firstly create a database connection

The query

Then create a database query, For maximum efficiency this should be a paged query with limit set to 1 so only 1 record is retrieved however for this tutorial i am going to use a standard query as the record count will server for a countdown

So query our table

we join these tables with an INNER join on addressid = geoaddressid and filter the results on isgeocoded == Null

image

and filter in isgeocoded is null

This will return all records in need of geocoding

Detecting if no records found

lastly we set a variable to indicate if records have been found. We will use this as an exit condition in app connect

The condition we will use is Query1,length

NOTE length is NOT available in the data picker to will need to be typed in manually

image

Obviously if you have named you query differently substitute your query name for Query1

make sure Output is checked

image

Save your server action

The API call

Now we will go to the API call which we will do in app connect

Create a page and add app connect and bootstrap, I have named mine massgeo.php

APP connect data connection

Let us first create a database connection to the new server action which i call conn_getnotgeo

image

Setting the address to geocode

next we need to build the full address from the returned data

Define a variable via Data =>Variable
I have left this as the default name var1

click the data picker and add the required address fields together using the magic wand

and use Operation + to add the fields

In my case i have only use the address1 line, zip and added the country manually as this is enough to uniquely identify an address in UK, you can add as many fields as required

Creating the API Call

Now we create a google API call in app connect

so go to Data=> API Data Source and add it

Your call will be to: https://maps.googleapis.com/maps/api/geocode/json

set your google key and the address as the variable you have just created. Sensor is an optional parameter in this case.

detecting the no data returned condition

Now create another variable. I will call mine varSwitch. it’s value is unimportant at this stage so set to an empty string.

image

Now add the browser component as we will need this soon

Now we need to go back to our server connection and add a dynamic event on success.

we are going to add two stages.

Firstly we will use browser,goto to leave the routine if no records are returned
If records are returned we will run the google API call

the first part requires some explanation but firstly create a new page, i call mine “done.php” i simply add a message to this saying “Done”

image

Now back in your massgeo.php page

We need to detect when no records are returned and conditionally run a browser,GoTo

There is no direct way to do this but there is a hack to do this

When defining a variable we can actually assign an action in place of a value

So in the set value stage we will use the returned variable hasreccords and type:

conn_getnogeo.data.hasrecords?0:browser1.goto(‘done.php’

Basically this statement is interpreted as:

if hasrecords is true then set the variable to 0 otherwise goto “done.php” (yes, a bit bizarre but it works)

We then add a load of the API call

image

So now if not data is returned the routine will stop and .goto “done.php” otherwise the API call will be made

The lat/lng update query

So now we need another server action to store the lat/lng returned

Create a server action, mine is called setgeo

Add 4 $_GET parameters as below

image

Next make your server connection

image

detecting geocode failure

we will be setting isgeocdoed to 1 if the geocode is successful and we will be setting it to 0 if the goecoding has failed

The api response returns “OK” of the goecodeing is successful so we use this to set if the goecode is successful

So go to core actions=> Set Value and call your variable geostatus

we now set this value according to the status returned from the google API so if status ids OK we set it to 1 otherwise 0

Set value geostatus = {{$_GET.status==‘OK’?1:0}}

image

the update query

Now we add a database update query i will leave as the default name update1

image

and we update the addressGeoCode table with the lat/ lng returned and the status as if this was a successful geocode using variable geostatus

and we will adda condition to set the unique record id which will be sent from app connect

Save the server action

Information messages (optional)

No we go back to outrpage massgeo.php

Firstly add the Notifications component which we will use for info/ diagnostic messages

Now go back to out API call in app connect and select Dynamic Events => API Connect => Success

Here i have firstly added some information messages using Notifications

In 4 messages i echo the API status, the lat, the lng and the value of hasrecords

image

Latitude

image

(api1.data.results[0].geometry.location.lat)

Longitude

(api1.data.results[0].geometry.location.lng)

and hasrecords

image

(conn_getnogeo.data.hasrecords)

calling update after geocoding via API

lastly we call the update query

image

Note we set the goecodeid field from the database connection settings

more diagnostic messages (optional)

Now i am going to add an info message on screen, i am going to add the value of var1.

So add a container, row and column

image

Now add a Content=> Paragraph and set it’s contents to var1.value. Add margins as wanted.

image

At this stage we should have a fully working geocode routine but at this stage it will only geocode 1 entry

Repeating via the action scheduler

Lastly we add the Action Scheduler

For demo purposes i will set the scheduler rate to every 5 seconds

On each tick of the scheduler we will simply re-calll the massgeo.php page

image

and that should be it so let us see a video of it in action on 6 records with a 1 second interval set in the action scheduler

Video of this in action

massgeocode.mp4 (1.1 MB)

4 Likes

Brilliant! Just what I need. Not read it all yet but one question, the database columns and their names, are they strict or just simply names that you have chosen? Just wondering how rigidly I have to follow your names and indeed number of fields etc. Cheers.

No, they are just examples which i based on @mimuk’s original request. All which would need to be changed are the appropriate references in the queries and set Variable statement. A one table solution would be suitable, i basically just join the two tables at the start and treat it as one anyway

1 Like

This is amazing! thanks @Hyperbytes
Cannot wait to give it a go.
You should setup something like a www.buymeacoffee.com account, I’d definitely throw a few quid for all your efforts.

Mim

I just wanted to say thank you to @Hyperbytes
His thorough walkthrough has enabled me to create a mass geocoding routine for my data set.

Mim

1 Like

Glad it all worked OK!

2 Likes