npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

lambda-taggable-geonames-indexer

v1.0.5

Published

Create Tags based on Geonames hierarchy

Downloads

16

Readme

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