geonames_local 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +1 -0
- data/README.rdoc +11 -25
- data/bin/geonames +2 -1
- data/geonames.yml +3 -3
- data/lib/geonames_local.rb +5 -10
- data/lib/geonames_local/cli.rb +31 -54
- data/lib/geonames_local/data/dump.rb +24 -11
- data/lib/geonames_local/data/shp.rb +1 -1
- data/lib/geonames_local/features/spot.rb +8 -33
- data/lib/geonames_local/geonames.rb +0 -5
- data/lib/geonames_local/models/mongodb.rb +157 -39
- data/lib/geonames_local/version.rb +1 -1
- data/spec/geonames_local/adapters/{postgres_spec.rb → postgis_spec.rb} +2 -2
- data/spec/geonames_local/features/spot_spec.rb +5 -7
- data/spec/geonames_local/models/{mongo_spec.rb → mongodb_spec.rb} +12 -9
- data/spec/geonames_local/models/postgis_spec.rb +73 -0
- data/spec/geonames_local_spec.rb +1 -0
- data/spec/spec_ar_helper.rb +96 -96
- data/spec/spec_helper.rb +1 -1
- metadata +8 -16
- data/lib/geonames_ar.rb +0 -12
- data/lib/geonames_cli.rb +0 -14
- data/lib/geonames_local/adapters/mongodb.rb +0 -109
- data/lib/geonames_local/adapters/postgres.rb +0 -108
- data/lib/geonames_local/adapters/tokyo.rb +0 -109
- data/lib/geonames_local/data/sync.rb +0 -74
- data/spec/geonames_local/models/ar_spec.rb +0 -73
- data/spec/spec_mongo_helper.rb +0 -6
data/lib/geonames_ar.rb
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Geonames Extension
|
3
|
-
#
|
4
|
-
$:.unshift(File.dirname(__FILE__)) unless
|
5
|
-
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
6
|
-
|
7
|
-
# Adapter = Geonames::Postgres.new(Opt[:db])
|
8
|
-
# Require Libs
|
9
|
-
require 'geonames_local/geonames'
|
10
|
-
|
11
|
-
require 'geonames_local/models/ar'
|
12
|
-
#require 'geonames_local/data/shp'
|
data/lib/geonames_cli.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# Geonames Local
|
3
|
-
#
|
4
|
-
$:.unshift(File.dirname(__FILE__)) unless
|
5
|
-
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
6
|
-
|
7
|
-
# Require CLI Stuff
|
8
|
-
require 'geonames_local/geonames'
|
9
|
-
require 'geonames_local/data/shp'
|
10
|
-
require 'geonames_local/data/dump'
|
11
|
-
require 'geonames_local/data/sync'
|
12
|
-
require 'geonames_local/data/export'
|
13
|
-
require 'geonames_local/cli'
|
14
|
-
|
@@ -1,109 +0,0 @@
|
|
1
|
-
require "mongo"
|
2
|
-
|
3
|
-
module Geonames
|
4
|
-
class Mongodb
|
5
|
-
|
6
|
-
RESOURCES = ["countries", "provinces", "cities"]
|
7
|
-
|
8
|
-
def initialize(params={})
|
9
|
-
host, port = params[:host] || "localhost", params[:port] || 27017
|
10
|
-
@conn = Mongo::Connection.new(host, port)
|
11
|
-
@db = @conn.db(params[:dbname] || "geonames")
|
12
|
-
if params[:user] || params[:password]
|
13
|
-
@db.authenticate(params[:user], params[:password])
|
14
|
-
end
|
15
|
-
if params[:purge]
|
16
|
-
info "Purging database.."
|
17
|
-
purge
|
18
|
-
end
|
19
|
-
setup
|
20
|
-
end
|
21
|
-
|
22
|
-
def setup
|
23
|
-
for re in RESOURCES
|
24
|
-
coll = @db.collection(re)
|
25
|
-
coll.create_index([["id", Mongo::ASCENDING], ["gid", Mongo::ASCENDING]])
|
26
|
-
|
27
|
-
# Geometric index, more info:
|
28
|
-
# http://www.mongodb.org/display/DOCS/Geospatial+Indexing
|
29
|
-
coll.create_index([["geom", Mongo::GEO2D]], :min => -180, :max => 180)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def all(resource, limit=nil, skip=0)
|
34
|
-
@db.collection(resource.to_s).find().to_a
|
35
|
-
end
|
36
|
-
|
37
|
-
def first(resource)
|
38
|
-
@db.collection(resource.to_s).find_one
|
39
|
-
end
|
40
|
-
|
41
|
-
def find(resource, id, name=nil)
|
42
|
-
@db.collection(resource.to_s).find_one("id" => id)
|
43
|
-
end
|
44
|
-
|
45
|
-
def find_by_name(resource, name)
|
46
|
-
do_find(resource, "name" => /#{name}/i)
|
47
|
-
end
|
48
|
-
|
49
|
-
def find_by_zip(resource, zip)
|
50
|
-
do_find(resource, "zip" => /#{zip}/)
|
51
|
-
end
|
52
|
-
|
53
|
-
def do_find(resource, hsh)
|
54
|
-
@db.collection(resource.to_s).find(hsh).to_a
|
55
|
-
end
|
56
|
-
|
57
|
-
def insert(resource, spot)
|
58
|
-
hsh = spot.to_hash
|
59
|
-
hsh["geom"][0] = sin_proj(hsh["geom"])[0] if hsh["geom"]
|
60
|
-
@db.collection(resource.to_s).insert(hsh)
|
61
|
-
end
|
62
|
-
|
63
|
-
def count(resource)
|
64
|
-
@db.collection(resource).count
|
65
|
-
end
|
66
|
-
|
67
|
-
def find_near(resource, x, y, limit=nil, skip=0)
|
68
|
-
coll = @db.collection(resource.to_s).find("geom" => { "$near" => { "x" => x, "y" => y }}).skip(skip)
|
69
|
-
coll.limit(limit) if limit
|
70
|
-
coll.to_a
|
71
|
-
end
|
72
|
-
|
73
|
-
# +1.3.4
|
74
|
-
def find_within(resource, geom, limit=nil)
|
75
|
-
op = geom[1].kind_of?(Numeric) ? "$center" : "$box"
|
76
|
-
coll = @db.collection(resource.to_s).find("geom" => { "$within" => { op => geom }})
|
77
|
-
coll.limit(limit) if limit
|
78
|
-
coll.to_a
|
79
|
-
end
|
80
|
-
|
81
|
-
# getNear command returns distance too
|
82
|
-
# <1.9 needs OrderedHash
|
83
|
-
def near(resource, x, y, limit=nil)
|
84
|
-
# FIXME: Better explicity require OrderedHash?
|
85
|
-
cmd = Object.const_defined?("OrderedHash") ? OrderedHash.new : { }
|
86
|
-
cmd["geoNear"] = resource
|
87
|
-
cmd["near"] = sin_proj(x,y)
|
88
|
-
cmd["num"] = limit if limit
|
89
|
-
@db.command(cmd)["results"].to_a
|
90
|
-
end
|
91
|
-
|
92
|
-
def purge
|
93
|
-
for re in RESOURCES
|
94
|
-
@db.drop_collection(re)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
def index_info(resource)
|
99
|
-
@db.collection(resource).index_information
|
100
|
-
end
|
101
|
-
|
102
|
-
private
|
103
|
-
|
104
|
-
def sin_proj(x,y=nil)
|
105
|
-
x,y = x unless y
|
106
|
-
[x * Math.cos(y * Math::PI/180), y]
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
@@ -1,108 +0,0 @@
|
|
1
|
-
require "pg"
|
2
|
-
|
3
|
-
module Geonames
|
4
|
-
class Postgres
|
5
|
-
Countries = {}
|
6
|
-
Provinces = {}
|
7
|
-
|
8
|
-
def initialize(opts={}) #table, addr = "localhost", port = 5432)
|
9
|
-
@conn = PGconn.new(opts)
|
10
|
-
end
|
11
|
-
|
12
|
-
#
|
13
|
-
# Get Country and Province ID from the DB
|
14
|
-
#
|
15
|
-
# Maps the FKs ids correctly for our bank
|
16
|
-
#
|
17
|
-
def get_some_ids(some)
|
18
|
-
cid = Countries[some.country] ||=
|
19
|
-
@conn.exec("SELECT countries.id FROM countries WHERE UPPER(countries.abbr) = UPPER('#{some.country}')")[0]["id"] rescue nil
|
20
|
-
cid ||= write("countries", {:name => Codes[some.country.downcase.to_sym][:pt_br], :abbr => some.country })
|
21
|
-
|
22
|
-
pid = nil
|
23
|
-
tid = nil
|
24
|
-
if some.kind_of? Spot
|
25
|
-
pid = Provinces[some.province] ||= find("provinces", Cache[:provinces].
|
26
|
-
find{ |p| p.province == some.province}.gid)
|
27
|
-
else
|
28
|
-
tid = find("cities", some.city)
|
29
|
-
pid = @conn.exec("SELECT cities.province_id FROM cities WHERE cities.id = #{tid}")[0]["province_id"] rescue nil
|
30
|
-
end
|
31
|
-
[cid, pid, tid]
|
32
|
-
end
|
33
|
-
|
34
|
-
#
|
35
|
-
# Insert a record
|
36
|
-
def insert(table, some)
|
37
|
-
country_id, province_id, city_id = get_some_ids(some)
|
38
|
-
case table
|
39
|
-
when :city
|
40
|
-
write("cities", {:name => some.name, :country_id => country_id,
|
41
|
-
:geom => some.geom.as_hex_ewkb, :gid => some.gid,
|
42
|
-
:zip => some.zip, :province_id => province_id})
|
43
|
-
when :province
|
44
|
-
write("provinces", { :name => some.name, :abbr => some.abbr,
|
45
|
-
:country_id => country_id, :gid => some.gid })
|
46
|
-
when :road
|
47
|
-
write("roads", { :name => some.name, :geom => some.geom.as_hex_ewkb, :kind => some.kind,
|
48
|
-
:country_id => country_id, :city_id => city_id, :province_id => province_id })
|
49
|
-
else
|
50
|
-
puts "Fail to insert #{some}"
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
#
|
55
|
-
# Find a record`s ID
|
56
|
-
def find(kind, id, name=nil)
|
57
|
-
table = get_table kind
|
58
|
-
begin
|
59
|
-
if name
|
60
|
-
@conn.exec("SELECT #{table}.id FROM #{table} WHERE (#{table}.name = E'#{id}')")[0]["id"]
|
61
|
-
else
|
62
|
-
@conn.exec("SELECT #{table}.id FROM #{table} WHERE #{table}.gid = #{id}")[0]["id"]
|
63
|
-
end
|
64
|
-
rescue => e
|
65
|
-
nil
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
#
|
70
|
-
# F'oo -> F''oo (for pg)
|
71
|
-
def escape_name(name)
|
72
|
-
name.to_s.gsub("'", "''")
|
73
|
-
end
|
74
|
-
|
75
|
-
#
|
76
|
-
# Sanitize values por pg.. here until my lazyness open pg rdoc...
|
77
|
-
def pg_values(arr)
|
78
|
-
arr.map do |v|
|
79
|
-
case v
|
80
|
-
when Numeric then v.to_s
|
81
|
-
when Symbol, String then "E'#{escape_name(v)}'"
|
82
|
-
when NilClass then 'NULL'
|
83
|
-
else
|
84
|
-
end
|
85
|
-
end.join(",")
|
86
|
-
end
|
87
|
-
|
88
|
-
def get_table(kind)
|
89
|
-
case kind
|
90
|
-
when :city then "cities"
|
91
|
-
when :country then "countries"
|
92
|
-
else
|
93
|
-
kind.to_s + "s"
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
#
|
98
|
-
# Naive PG insert ORM =D
|
99
|
-
def write(table, hsh)
|
100
|
-
for_pg = pg_values(hsh.values)
|
101
|
-
@conn.exec("INSERT INTO #{table} (#{hsh.keys.join(",")}) VALUES(#{for_pg}) RETURNING id")[0]["id"]
|
102
|
-
end
|
103
|
-
|
104
|
-
def exec(comm)
|
105
|
-
@conn.exec(comm)
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
@@ -1,109 +0,0 @@
|
|
1
|
-
require "tokyocabinet"
|
2
|
-
|
3
|
-
module Geonames
|
4
|
-
class Tokyo
|
5
|
-
|
6
|
-
def initialize(conn=nil, resource=nil, extra=nil)
|
7
|
-
if conn
|
8
|
-
require 'tokyotyrant'
|
9
|
-
resource ||= 'localhost'
|
10
|
-
extra ||= 1978
|
11
|
-
@tbl = TokyoTyrant::RDBTBL
|
12
|
-
@qry = TokyoTyrant::RDBQRY
|
13
|
-
else
|
14
|
-
require 'tokyocabinet'
|
15
|
-
resource ||= 'geonames.tct'
|
16
|
-
extra ||= (TokyoCabinet::TDB::OWRITER | TokyoCabinet::TDB::OCREAT)
|
17
|
-
@tbl = TokyoCabinet::TDB
|
18
|
-
@qry = TokyoCabinet::TDBQRY
|
19
|
-
end
|
20
|
-
@rdb = @tbl.new
|
21
|
-
@rdb.open(resource, extra)
|
22
|
-
set_indexes
|
23
|
-
end
|
24
|
-
|
25
|
-
def all(params)
|
26
|
-
qry = @qry.new(@rdb)
|
27
|
-
params.each do |k,v|
|
28
|
-
#qry.addcond(k.to_s, Q::QCNUMEQ, v.to_s)
|
29
|
-
qry.addcond(k.to_s, @qry::QCSTREQ, v.to_s)
|
30
|
-
end
|
31
|
-
qry.setorder("name", @qry::QOSTRASC)
|
32
|
-
qry.search.map { |id| @rdb.get(id) }
|
33
|
-
end
|
34
|
-
|
35
|
-
def find(id)
|
36
|
-
#qry = Q.new(@rdb)
|
37
|
-
#qry.addcond("gid", Q::QCNUMEQ, id.to_s)
|
38
|
-
#qry.setlimit(10)
|
39
|
-
#id = qry.search.pop
|
40
|
-
@rdb.get(id)
|
41
|
-
end
|
42
|
-
|
43
|
-
# def to_obj(hsh)
|
44
|
-
# hsh["kind"] == "country" ? Country.new(hsh) : Spot.new(hsh)
|
45
|
-
# end
|
46
|
-
|
47
|
-
def write(o)
|
48
|
-
# pkey = @rdb.genuid
|
49
|
-
if @rdb.put(o.gid, o.to_hash)
|
50
|
-
# info "ok"
|
51
|
-
else
|
52
|
-
info "err #{@rdb.errmsg(@rdb.ecode)}"
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def count
|
57
|
-
@qry.new(@rdb).search.length
|
58
|
-
end
|
59
|
-
|
60
|
-
def close
|
61
|
-
# close the database
|
62
|
-
if !@rdb.close
|
63
|
-
STDERR.printf("close error: %s\n", @rdb.errmsg(@rdb.ecode))
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def set_indexes
|
68
|
-
#for index in indexes
|
69
|
-
# @rdb.setindex("gid", @tbl::ITOPT)
|
70
|
-
@rdb.setindex("kind", @tbl::ITLEXICAL)
|
71
|
-
@rdb.setindex("name", @tbl::ITQGRAM)
|
72
|
-
@rdb.setindex("country", @tbl::ITLEXICAL)
|
73
|
-
|
74
|
-
#end
|
75
|
-
|
76
|
-
end
|
77
|
-
|
78
|
-
def flush
|
79
|
-
@rdb.vanish
|
80
|
-
end
|
81
|
-
|
82
|
-
|
83
|
-
end
|
84
|
-
|
85
|
-
end
|
86
|
-
|
87
|
-
# def self.point(tdb, x, y)
|
88
|
-
# qry = TDBQRY::new(tdb)
|
89
|
-
# qry.addcond("x", TDBQRY::QCNUMGE, minx.to_s())
|
90
|
-
# qry.addcond("x", TDBQRY::QCNUMLE, maxx.to_s())
|
91
|
-
# qry.addcond("y", TDBQRY::QCNUMGE, miny.to_s())
|
92
|
-
# qry.addcond("y", TDBQRY::QCNUMLE, maxy.to_s())
|
93
|
-
# qry.setorder("x", TDBQRY::QONUMASC)
|
94
|
-
# qry.setlimit(80)
|
95
|
-
# end
|
96
|
-
|
97
|
-
|
98
|
-
# def self.area(tdb, minx, maxx, miny, maxy)
|
99
|
-
# qry = TDBQRY::new(tdb)
|
100
|
-
# qry.addcond("x", TDBQRY::QCNUMGE, minx.to_s())
|
101
|
-
# qry.addcond("x", TDBQRY::QCNUMLE, maxx.to_s())
|
102
|
-
# qry.addcond("y", TDBQRY::QCNUMGE, miny.to_s())
|
103
|
-
# qry.addcond("y", TDBQRY::QCNUMLE, maxy.to_s())
|
104
|
-
# qry.setorder("x", TDBQRY::QONUMASC)
|
105
|
-
|
106
|
-
# res = qry.search
|
107
|
-
# info res.length # number of results found
|
108
|
-
# return res
|
109
|
-
# end
|
@@ -1,74 +0,0 @@
|
|
1
|
-
module Geonames
|
2
|
-
class Sync
|
3
|
-
class << self
|
4
|
-
|
5
|
-
def work!
|
6
|
-
unify!
|
7
|
-
write_to_store!
|
8
|
-
end
|
9
|
-
|
10
|
-
def load_adapter(name)
|
11
|
-
begin
|
12
|
-
require "geonames_local/adapters/#{name}"
|
13
|
-
Geonames.class_eval(name.capitalize).new(Opt[:db])
|
14
|
-
rescue LoadError
|
15
|
-
puts "Can't find adapter #{name}"
|
16
|
-
stop!
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def write_to_store!
|
21
|
-
groups = Cache[:dump].group_by(&:kind)
|
22
|
-
Cache[:provinces] = groups[:province]
|
23
|
-
# ensure this order....
|
24
|
-
do_write(groups[:province])
|
25
|
-
do_write(groups[:city])
|
26
|
-
end
|
27
|
-
|
28
|
-
def do_write(values)
|
29
|
-
return if values.empty?
|
30
|
-
db = load_adapter(Opt[:store])
|
31
|
-
key = values[0].table
|
32
|
-
start = Time.now
|
33
|
-
writt = 0
|
34
|
-
min_pop = Opt[:min_pop]
|
35
|
-
info "\nWriting #{values.length} #{key}..."
|
36
|
-
info "\nWriting spots with pop > #{Opt[:min_pop]} hab." if min_pop
|
37
|
-
values.each do |val|
|
38
|
-
if min_pop
|
39
|
-
next unless val.pop && val.pop.to_i >= min_pop
|
40
|
-
end
|
41
|
-
arg = val.respond_to?(:gid) ? [val.gid] : [val.name, true]
|
42
|
-
unless db.find(val.table, *arg)
|
43
|
-
db.insert(val.table, val)
|
44
|
-
writt += 1
|
45
|
-
end
|
46
|
-
end
|
47
|
-
total = Time.now - start
|
48
|
-
info "#{writt} #{key} written in #{total} sec (#{(writt/total).to_i}/s)"
|
49
|
-
end
|
50
|
-
|
51
|
-
def unify!
|
52
|
-
info "Join dump << zip"
|
53
|
-
start = Time.now
|
54
|
-
Cache[:dump].map! do |spot|
|
55
|
-
if other = Cache[:zip].find { |d| d.code == spot.code }
|
56
|
-
spot.zip = other.zip
|
57
|
-
spot
|
58
|
-
else
|
59
|
-
spot
|
60
|
-
end
|
61
|
-
end
|
62
|
-
info "Done. #{(Time.now-start).to_i}s"
|
63
|
-
end
|
64
|
-
|
65
|
-
def stop!
|
66
|
-
puts "Closing Geonames..."
|
67
|
-
exit
|
68
|
-
end
|
69
|
-
|
70
|
-
end
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|
@@ -1,73 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
require File.expand_path(File.dirname(__FILE__) + '/../../spec_ar_helper')
|
3
|
-
module Geonames
|
4
|
-
module Models
|
5
|
-
module AR
|
6
|
-
class User < ActiveRecord::Base
|
7
|
-
belongs_to :city
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def brasil
|
14
|
-
Models::AR::Country.find_or_create_by_name(:name => "Brazil", :abbr => "BR")
|
15
|
-
end
|
16
|
-
|
17
|
-
describe "Country" do
|
18
|
-
|
19
|
-
it "should create countries" do
|
20
|
-
Models::AR::Country.create(:name => "Chad", :abbr => "TD").should be_valid
|
21
|
-
end
|
22
|
-
|
23
|
-
it "should write to db" do
|
24
|
-
lambda do
|
25
|
-
Models::AR::Country.create(:name => "Itália", :abbr => "IT")
|
26
|
-
end.should change(Models::AR::Country, :count).by(1)
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
describe "Province" do
|
32
|
-
|
33
|
-
it "should be a class instance of ar" do
|
34
|
-
Models::AR::Province.new.should be_instance_of Models::AR::Province
|
35
|
-
end
|
36
|
-
|
37
|
-
it "should create" do
|
38
|
-
Models::AR::Province.create(:name => "Chadland", :country => brasil).should be_valid
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
describe "City" do
|
43
|
-
|
44
|
-
it "should be a class instance of ar" do
|
45
|
-
Models::AR::City.new.should be_instance_of Models::AR::City
|
46
|
-
end
|
47
|
-
|
48
|
-
it "should create" do
|
49
|
-
Models::AR::City.create(:name => "Chadland", :country => brasil).should be_valid
|
50
|
-
end
|
51
|
-
end
|
52
|
-
# DatabaseCleaner.clean
|
53
|
-
|
54
|
-
describe "Active Record Stuff" do
|
55
|
-
|
56
|
-
before do
|
57
|
-
# DatabaseCleaner.clean
|
58
|
-
@br ||= brasil
|
59
|
-
Models::AR::City.create!("name" => "São Tomé", "geom" => [15,15], :country => @br)
|
60
|
-
Models::AR::City.create!("name" => "Rock CIty", "geom" => [18,16], :country => @br)
|
61
|
-
end
|
62
|
-
|
63
|
-
it "should record" do
|
64
|
-
Models::AR::City.count.should eql(2)
|
65
|
-
end
|
66
|
-
|
67
|
-
it "should create" do
|
68
|
-
user = Models::AR::User.new(:name => "Defendor")
|
69
|
-
user.city = Models::AR::City.first
|
70
|
-
user.save
|
71
|
-
Models::AR::User.first.city.name.should eql("São Tomé")
|
72
|
-
end
|
73
|
-
end
|