Skip to content

Model: GeonamesGeoname

yurtesen edited this page Oct 16, 2016 · 2 revisions

This is the model for the main table of Geonames. It includes all the cities, regions, countries, continents and everything else. You need to add your own indices to database based on your usage patterns.

Table Structure

The table structure is mostly based on the information from geonames site with minimal set of indices.

Field Type Null Key Default Extra
geoname_id int(10) unsigned NO PRI NULL
name varchar(200) NO NULL
ascii_name varchar(200) YES NULL
alternate_names varchar(10000) YES NULL
latitude decimal(7,5) NO NULL
longitude decimal(8,5) NO NULL
feature_class char(1) YES NULL
feature_code varchar(10) YES NULL
country_code char(2) NO NULL
cc2 varchar(60) YES NULL
admin1_code varchar(20) YES NULL
admin2_code varchar(80) YES NULL
admin3_code varchar(20) YES NULL
admin4_code varchar(20) YES NULL
population int(10) unsigned YES NULL
elevation int(11) YES NULL
dem int(11) YES NULL
timezone_id varchar(40) YES MUL NULL
modified_at date NO NULL

Relations

The model provides few relations for easy data access. Please remember to read the documentation and API examples for Eloquent relationships.

alternateName

This relation assumes that you have imported alternatenames table which is not imported by default. Because the main GeonamesGeoname model already has a bunch of alternate names listed in alternate_names column separated by comma.

>>> GeonamesGeoname::City('Turku')->first()->alternateName;
=> Yurtesen\Geonames\Models\GeonamesAlternateName {#858
     alternate_name_id: 11321790,
     geoname_id: 633679,
     iso_language: "ur",
     alternate_name: "ترکو",
     isPreferredName: 0,
     isShortName: 0,
     isColloquial: 0,
     isHistoric: 1,
   }
>>>

timeZone

This relation returns the timeZone information about the location. Notice that the timezone_id in GeonamesGeoname model is a text field which already has the timezone as text, eg. "Europe/Helsinki".

>>> GeonamesGeoname::City('Turku')->first()->timeZone;
=> Yurtesen\Geonames\Models\GeonamesTimezone {#861
     timezone_id: "Europe/Helsinki",
     country_code: "FI",
     gmt_offset: "2.0",
     dst_offset: "3.0",
     raw_offset: "2.0",
   }
>>>

country

This relation returns the information about the country where the location resides.

>>> GeonamesGeoname::City('Turku')->first()->countryInfo;
=> Yurtesen\Geonames\Models\GeonamesCountryInfo {#876
     iso: "FI",
     iso3: "FIN",
     iso_numeric: "246",
     fips: "FI",
     country: "Finland",
     capital: "Helsinki",
     area: 337030,
     population: 5244000,
     continent_code: "EU",
     continent_id: 6255148,
     tld: ".fi",
     currency_code: "EUR",
     currency_name: "Euro",
     phone: "358",
     postal_code_format: "#####",
     postal_code_regex: "^(?:FI)*(\d{5})$",
     languages: "fi-FI,sv-FI,smn",
     geoname_id: 660013,
     neighbors: "NO,RU,SE",
     equivalent_fips_code: "",
   }
>>>

Scopes

These scopes are used to build queries which fetches relevant information. More select fields can be added using addSelect() method.

admin1

This scope uses the admin1 code from the GeonamesGeoname model to fetch administrative region information

>>> GeonamesGeoname::City('Turku')->admin1()->get();
=> Illuminate\Database\Eloquent\Collection {#867
     all: [
       Yurtesen\Geonames\Models\GeonamesGeoname {#868
         geoname_id: 633679,
         name: "Turku",
         country_code: "FI",
         admin1_geoname_id: 830708,
         admin1_name: "Southwest Finland",
       },
     ],
   }

addCountryInfo

This scope returns the basic information about the country where the location resides.

>>> GeonamesGeoname::City('Turku')->addCountryInfo()->get();
=> Illuminate\Database\Eloquent\Collection {#870
     all: [
       Yurtesen\Geonames\Models\GeonamesGeoname {#871
         geoname_id: 633679,
         name: "Turku",
         country_code: "FI",
         country_info_geoname_id: 660013,
         country_info_country: "Finland",
       },
     ],
   }
>>>

city($name, $featureCodes= ['PPLC', 'PPLA', 'PPLA2', 'PPLA3']), country($name, $featureCodes= ['PCLI'])

Both 'city' and 'country' scopes function similarly. The difference is, 'city' scope uses feature class 'P' and 'country' scope uses feature class 'A' and different default feature codes.

City scope returns reasonable size towns. The optional $featureCodes array provides a way to widen the search. (eg. by adding PPLA4 to the array)

It is recommended to create an index before using this scope. The following index seem to work fine. If you have a better index idea, please let us know. ALTER TABLE geonames_geonames ADD index (feature_code,feature_class,name);

The $name variable accepts wildcards. For example 'Turk%' and also query builder functions like limit(), orderBy() etc. can be used. Using a wildcard as a prefix (eg. '%Turk%') is not recommended since it will not allow efficient index usage. Please see the MySQL manual for usage of indices. Below is an example which shows the performance difference:

>>> $microtime=microtime(true); GeonamesGeoname::City('A%')->get(); microtime(true)-$microtime;
=> 0.15125107765198
>>> $microtime=microtime(true); GeonamesGeoname::City('%A%')->get(); microtime(true)-$microtime;
=> 1.3731260299683
>>>

In the example below, notice that the search string uses ASCII characters but MySQL still finds results with UTF-8 equivalents of these characters. Eg. 'u' <-> 'ü'

>>> GeonamesGeoname::City('Turk%')->limit(2)->get();
=> Illuminate\Database\Eloquent\Collection {#877
     all: [
       Yurtesen\Geonames\Models\GeonamesGeoname {#878
         geoname_id: 1219649,
         name: "Türkmenabat",
         ascii_name: "Turkmenabat",
         alternate_names: "CRZ,Chardzha,Chardzhev,Chardzhou,Chardzhui,Chardzhuy,Charjew,Charjou,Chärjew,Leninsk-Turkmenski,Leninsk-Turmenski,Nov Charjui,Nov Chārjui,Novo Chardzhou,Novo-Chardzhuy,Tuerkmenabat,Turkmanobod,Turkmenabad,Turkmenabat,Turkmenabatas,Türkmenabat,Türkmənabad,te~yurukumenabato,trkman abad,trkmn abad,tu ku man na ba de,tuleukeumenabateu,turkamenabata,turkmenabadi,Туркменабад,Туркменабат,Түркменабат,Չարզոու,ترکمان آباد,ترکمن آباد,ترکمن‌آباد,तुर्कमेनाबात,თურქმენაბადი,テュルクメナバート,土庫曼納巴德,투르크메나바트",
         latitude: "39.07328",
         longitude: "63.57861",
         feature_class: "P",
         feature_code: "PPLA",
         country_code: "TM",
         cc2: null,
         admin1_code: "04",
         admin2_code: null,
         admin3_code: null,
         admin4_code: null,
         population: 234817,
         elevation: null,
         dem: 191,
         timezone_id: "Asia/Ashgabat",
         modified_at: "2014-08-19",
       },
       Yurtesen\Geonames\Models\GeonamesGeoname {#879
         geoname_id: 633679,
         name: "Turku",
         ascii_name: "Turku",
         alternate_names: "Abo,Aboa,Gorad Turku,TKU,Tourkou,Turcu,Turku,Turkù,Turu,Túrcú,to~uruku,trkw,tu er ku,tu rku,tuleuku,turku,twrkw,twrqw,Åbo,Τούρκου,Горад Турку,Турку,Տուրկու,טורקו,ترکو,توركو,تورکو,तुर्कू,টুর্কু,ตุรกุ,တားကူးမြို့,ტურკუ,ቱርኩ,トゥルク,图尔库,圖爾庫,투르쿠",
         latitude: "60.45148",
         longitude: "22.26869",
         feature_class: "P",
         feature_code: "PPLA",
         country_code: "FI",
         cc2: null,
         admin1_code: "02",
         admin2_code: "023",
         admin3_code: "853",
         admin4_code: null,
         population: 175945,
         elevation: null,
         dem: 22,
         timezone_id: "Europe/Helsinki",
         modified_at: "2016-07-23",
       },
     ],
   }
>>>