lambda-taggable-geonames-indexer

1.0.5 • Public • Published

Lambda Taggable Geonames

Codeship codecov.io

Why?

Locating Hotels and other content by searching for a place name is the heart of the Tagging system. We use Geonames to "reverse geocode" the Lat/Lon for each Hotel in the database and add "hierarchy" for that place.

See: How? > Detail section for detailed example

What?

Lambda function that accepts a set of Longitude & Latitude coordinates (lat/lon) and returns a list of Geo Tags. (corresponding to the elements in the Geonames hierarchy for that lat/lon).

How?

There are two ways to use this package:

Lambda

  1. Deploy the Lambda function by running the deployment script: npm run deploy
    ( see: https://github.com/numo-labs/aws-lambda-deploy for detail )

  2. Invoke in AWS Console:

Sample Event

{
  "_id": "hotel:mhid.02tu1jz",
  "displayName": "Elvis Presley's Heartbreak",
  "location": {
    "lat": "35.04850",
    "lon": "-90.02710"
  },
  "tags": []
}

Will return an array of Geo Tags in the Taggable System format:

[
  {
    "_id": "geo:geonames.6295630",
    "displayName": "Earth",
    "location": {
      "lat": "0",
      "lon": "0"
    },
    "tags": []
  },
  {
    "_id": "geo:geonames.6255149",
    "displayName": "North America",
    "location": {
      "lat": "46.07323",
      "lon": "-100.54688"
    },
    "tags": [
      {
        "tagId": "geo:geonames.6295630",
        "displayName": "Earth",
        "source": "geonames",
        "inherited": false,
        "active": true
      }
    ]
  },
  {
    "_id": "geo:geonames.6252001",
    "displayName": "United States",
    "location": {
      "lat": "39.76",
      "lon": "-98.5"
    },
    "tags": [
      {
        "tagId": "geo:geonames.6255149",
        "displayName": "North America",
        "source": "geonames",
        "inherited": false,
        "active": true
      },
      {
        "tagId": "geo:geonames.6295630",
        "displayName": "Earth",
        "source": "geonames",
        "inherited": false,
        "active": true
      }
    ]
  },
  {
    "_id": "geo:geonames.4662168",
    "displayName": "Tennessee",
    "location": {
      "lat": "35.75035",
      "lon": "-86.25027"
    },
    "tags": [
      {
        "tagId": "geo:geonames.6252001",
        "displayName": "United States",
        "source": "geonames",
        "inherited": false,
        "active": true
      },
      {
        "tagId": "geo:geonames.6255149",
        "displayName": "North America",
        "source": "geonames",
        "inherited": false,
        "active": true
      },
      {
        "tagId": "geo:geonames.6295630",
        "displayName": "Earth",
        "source": "geonames",
        "inherited": false,
        "active": true
      }
    ]
  },
  {
    "_id": "geo:geonames.4657046",
    "displayName": "Shelby County",
    "location": {
      "lat": "35.184",
      "lon": "-89.8956"
    },
    "tags": [
      {
        "tagId": "geo:geonames.4662168",
        "displayName": "Tennessee",
        "source": "geonames",
        "inherited": false,
        "active": true
      },
      {
        "tagId": "geo:geonames.6252001",
        "displayName": "United States",
        "source": "geonames",
        "inherited": false,
        "active": true
      },
      {
        "tagId": "geo:geonames.6255149",
        "displayName": "North America",
        "source": "geonames",
        "inherited": false,
        "active": true
      },
      {
        "tagId": "geo:geonames.6295630",
        "displayName": "Earth",
        "source": "geonames",
        "inherited": false,
        "active": true
      }
    ]
  },
  {
    "_id": "geo:geonames.4645760",
    "displayName": "Nonconnah",
    "location": {
      "lat": "35.06204",
      "lon": "-90.0362"
    },
    "tags": [
      {
        "tagId": "geo:geonames.4657046",
        "displayName": "Shelby County",
        "source": "geonames",
        "inherited": false,
        "active": true
      },
      {
        "tagId": "geo:geonames.4662168",
        "displayName": "Tennessee",
        "source": "geonames",
        "inherited": false,
        "active": true
      },
      {
        "tagId": "geo:geonames.6252001",
        "displayName": "United States",
        "source": "geonames",
        "inherited": false,
        "active": true
      },
      {
        "tagId": "geo:geonames.6255149",
        "displayName": "North America",
        "source": "geonames",
        "inherited": false,
        "active": true
      },
      {
        "tagId": "geo:geonames.6295630",
        "displayName": "Earth",
        "source": "geonames",
        "inherited": false,
        "active": true
      }
    ]
  }
]

Node Module

If you prefer to use this package as a node module e.g: as part of another lambda

npm install lambda-taggable-geonames-indexer --save

Then in your code:

var geonames = require('lambda-taggable-geonames-indexer');
var lat = '28.3852';
var lon = '81.5639';
geonames.find(lat, lon, function (err, geo) {
  console.log(geo); // see Detail section below for example output
  var geonames_id = geo.geonames[0].geonameId;
  geonames.hierarchy(geonames_id, function (err, hierarchy) {
    console.log(JSON.stringify(hierarchy, null, 2));
  }); // see Detail for example hierarchy object
});

Detail

The best way to understand how this works is with a simple example:

Imagine we have a Hotel in Formenterra

{
    "MID": "1234ABCD",
    "Name": "Blanco Hotel Formentera",
    "Country": "SPAIN",
    "ISO-2": "ES",
    "Address": "Calle Fonoll Marí, 50 07871 Es Pujols",
    "Latitude": "38.7",
    "Longitude": "1.467"
  }

We would lookup this hotel in Geonames given its Latitude and Longitude values using the following query:

http://api.geonames.org/findNearbyPlaceNameJSON?lat=38.7&lng=1.467&username=demo&style=full&localCountry=true&maxrows=100&cities=15000

{  
   "geonames":[  
      {  
         "distance":"1.31434",
         "timezone":{  
            "gmtOffset":1,
            "timeZoneId":"Europe/Madrid",
            "dstOffset":2
         },
         "asciiName":"Sant Ferran de ses Roques",
         "countryId":"2510769",
         "fcl":"P",
         "adminId2":"6424360",
         "adminId3":"6356033",
         "countryCode":"ES",
         "adminId1":"2521383",
         "lat":"38.70762",
         "fcode":"PPL",
         "continentCode":"EU",
         "elevation":0,
         "adminCode2":"PM",
         "adminCode3":"07024",
         "adminCode1":"07",
         "lng":"1.45543",
         "geonameId":6696037,
         "toponymName":"Sant Ferran de ses Roques",
         "population":10757,
         "adminName5":"",
         "adminName4":"",
         "adminName3":"Formentera",
         "alternateNames":[  
            {  
               "name":"http://en.wikipedia.org/wiki/Sant_Ferran_de_ses_Roques",
               "lang":"link"
            }
         ],
         "adminName2":"Balearic Islands",
         "name":"Sant Ferran de ses Roques",
         "fclName":"city, village,...",
         "countryName":"Spain",
         "fcodeName":"populated place",
         "adminName1":"Balearic Islands"
      }
   ]
}

From this response get the geonameId which we can use to run the hierarchy query: http://api.geonames.org/hierarchyJSON?geonameId=6696037&username=demo

{  
   "geonames":[  
      {  
         "lng":"0",
         "geonameId":6295630,
         "name":"Earth",
         "fclName":"parks,area, ...",
         "toponymName":"Earth",
         "fcodeName":"area",
         "adminName1":"",
         "lat":"0",
         "fcl":"L",
         "fcode":"AREA",
         "population":6814400000
      },
      {  
         "lng":"9.14062",
         "geonameId":6255148,
         "name":"Europe",
         "fclName":"parks,area, ...",
         "toponymName":"Europe",
         "fcodeName":"continent",
         "adminName1":"",
         "lat":"48.69096",
         "fcl":"L",
         "fcode":"CONT",
         "population":0
      },
      {  
         "adminCode1":"00",
         "lng":"-4",
         "geonameId":2510769,
         "toponymName":"Kingdom of Spain",
         "countryId":"2510769",
         "fcl":"A",
         "population":46505963,
         "countryCode":"ES",
         "name":"Spain",
         "fclName":"country, state, region,...",
         "countryName":"Spain",
         "fcodeName":"independent political entity",
         "adminName1":"",
         "lat":"40",
         "fcode":"PCLI"
      },
      {  
         "adminCode1":"07",
         "lng":"1.45871",
         "geonameId":6356033,
         "toponymName":"Formentera",
         "countryId":"2510769",
         "fcl":"A",
         "population":10757,
         "countryCode":"ES",
         "name":"Formentera",
         "fclName":"country, state, region,...",
         "countryName":"Spain",
         "fcodeName":"third-order administrative division",
         "adminName1":"Balearic Islands",
         "lat":"38.71905",
         "fcode":"ADM3"
      }
   ]
}

Expected Environment Variables

Running the Lambda/Script

Using this script requires that you set a GEONAMES_USERNAMES environment variable (one or more usernames) e.g:

export GEONAMES_USERNAME=yourusername,backupusername,etc

Deploying

Deploying to AWS requires that you set AWS_REGION and AWS_IAM_ROLE variables.

e.g:

export AWS_REGION=eu-west-1
export AWS_IAM_ROLE=arn:aws:iam::123456789:role/LambdaExecRole

see: https://github.com/numo-labs/aws-lambda-deploy#2-ensure-that-the-required-aws-environment-variables-are-set

Setup Geonames Account

To use this module you will require a Geonames account. If you have not already signed up, visit: http://www.geonames.org/login

Next, ensure that you have enabled the "Free Web Service" for your Geonames account:

Go to: http://www.geonames.org/manageaccount and scroll to the bottom of the page geonames-manageaccount-enable-free-web-services you will see a link "Click here to enable" click it.

Once enabled you should see a confirmation message: geonames-free-webservice-enabled

Now everything should work as expected.

Running low on Geonames API Calls/Credits?

see: https://github.com/numo-labs/lambda-taggable-geonames-indexer/issues/5

Tests

to run the tests for this project execute the following command in your terminal:

npm test

Readme

Keywords

Package Sidebar

Install

npm i lambda-taggable-geonames-indexer

Weekly Downloads

2

Version

1.0.5

License

ISC

Last publish

Collaborators

  • nelsonic