地理編碼 — 接收一個地址字串(或其他標準化地址),並輸出可能的地理位置集合,其中包含以 NAD 83 經緯度表示的點幾何、每個位置的標準化地址和評分。評分越低,匹配的可能性越高。結果會先以評分最低的排序。可以選擇性地傳入最大結果數(預設為 10)和 restrict_region(預設為 NULL)
setof record geocode(
varchar address, integer max_results=10, geometry restrict_region=NULL, norm_addy OUT addy, geometry OUT geomout, integer OUT rating)
;
setof record geocode(
norm_addy in_addy, integer max_results=10, geometry restrict_region=NULL, norm_addy OUT addy, geometry OUT geomout, integer OUT rating)
;
接收一個地址字串(或已經標準化的地址),並輸出可能的地理位置集合,其中包含以 NAD 83 經緯度表示的點幾何、每個位置的 normalized_address
(addy) 和評分。評分越低,匹配的可能性越高。結果會先以評分最低的排序。使用 Tiger 資料(邊、面、地址)、PostgreSQL 模糊字串匹配(soundex、levenshtein)和 PostGIS 線性內插函數,沿著 Tiger 邊緣內插地址。評分越高,地理編碼正確的可能性越低。地理編碼點預設從街道地址所在位置的中心線偏移 10 公尺到側邊(左/右)。
增強功能:2.0.0 版本支援 Tiger 2010 結構化資料,並修訂了一些邏輯以提高地理編碼的速度和準確性,以及將點從中心線偏移到街道地址所在的一側。新的參數 max_results
對於指定最佳結果的數量或僅返回最佳結果非常有用。
以下範例的計時是在配備 2GB 記憶體的 3.0 GHZ 單處理器 Windows 7 電腦上執行,該電腦執行 PostgreSQL 9.1rc1/PostGIS 2.0 並載入了所有 MA、MN、CA、RI 州的 Tiger 資料。
精確匹配計算速度更快 (61ms)
SELECT g.rating, ST_X(g.geomout) As lon, ST_Y(g.geomout) As lat, (addy).address As stno, (addy).streetname As street, (addy).streettypeabbrev As styp, (addy).location As city, (addy).stateabbrev As st,(addy).zip FROM geocode('75 State Street, Boston MA 02109', 1) As g; rating | lon | lat | stno | street | styp | city | st | zip --------+-------------------+----------------+------+--------+------+--------+----+------- 0 | -71.0557505845646 | 42.35897920691 | 75 | State | St | Boston | MA | 02109
即使沒有傳入郵遞區號,地理編碼器也可以猜測 (大約需要 122-150 毫秒)
SELECT g.rating, ST_AsText(ST_SnapToGrid(g.geomout,0.00001)) As wktlonlat, (addy).address As stno, (addy).streetname As street, (addy).streettypeabbrev As styp, (addy).location As city, (addy).stateabbrev As st,(addy).zip FROM geocode('226 Hanover Street, Boston, MA',1) As g; rating | wktlonlat | stno | street | styp | city | st | zip --------+---------------------------+------+---------+------+--------+----+------- 1 | POINT(-71.05528 42.36316) | 226 | Hanover | St | Boston | MA | 02113
可以處理拼寫錯誤,並提供多個具有評分的可能解決方案,需要更長的時間 (500 毫秒)。
SELECT g.rating, ST_AsText(ST_SnapToGrid(g.geomout,0.00001)) As wktlonlat, (addy).address As stno, (addy).streetname As street, (addy).streettypeabbrev As styp, (addy).location As city, (addy).stateabbrev As st,(addy).zip FROM geocode('31 - 37 Stewart Street, Boston, MA 02116',1) As g; rating | wktlonlat | stno | street | styp | city | st | zip --------+---------------------------+------+--------+------+--------+----+------- 70 | POINT(-71.06466 42.35114) | 31 | Stuart | St | Boston | MA | 02116
用於對地址進行批次地理編碼。最簡單的方法是設定 max_results=1
。僅處理那些尚未進行地理編碼的地址(沒有評分)。
CREATE TABLE addresses_to_geocode(addid serial PRIMARY KEY, address text, lon numeric, lat numeric, new_address text, rating integer); INSERT INTO addresses_to_geocode(address) VALUES ('529 Main Street, Boston MA, 02129'), ('77 Massachusetts Avenue, Cambridge, MA 02139'), ('25 Wizard of Oz, Walaford, KS 99912323'), ('26 Capen Street, Medford, MA'), ('124 Mount Auburn St, Cambridge, Massachusetts 02138'), ('950 Main Street, Worcester, MA 01610'); -- only update the first 3 addresses (323-704 ms - there are caching and shared memory effects so first geocode you do is always slower) -- -- for large numbers of addresses you don't want to update all at once -- since the whole geocode must commit at once -- For this example we rejoin with LEFT JOIN -- and set to rating to -1 rating if no match -- to ensure we don't regeocode a bad address UPDATE addresses_to_geocode SET (rating, new_address, lon, lat) = ( COALESCE(g.rating,-1), pprint_addy(g.addy), ST_X(g.geomout)::numeric(8,5), ST_Y(g.geomout)::numeric(8,5) ) FROM (SELECT addid, address FROM addresses_to_geocode WHERE rating IS NULL ORDER BY addid LIMIT 3) As a LEFT JOIN LATERAL geocode(a.address,1) As g ON true WHERE a.addid = addresses_to_geocode.addid; result ----- Query returned successfully: 3 rows affected, 480 ms execution time. SELECT * FROM addresses_to_geocode WHERE rating is not null; addid | address | lon | lat | new_address | rating -------+----------------------------------------------+-----------+----------+-------------------------------------------+-------- 1 | 529 Main Street, Boston MA, 02129 | -71.07177 | 42.38357 | 529 Main St, Boston, MA 02129 | 0 2 | 77 Massachusetts Avenue, Cambridge, MA 02139 | -71.09396 | 42.35961 | 77 Massachusetts Ave, Cambridge, MA 02139 | 0 3 | 25 Wizard of Oz, Walaford, KS 99912323 | -97.92913 | 38.12717 | Willowbrook, KS 67502 | 108 (3 rows)
SELECT g.rating, ST_AsText(ST_SnapToGrid(g.geomout,0.00001)) As wktlonlat, (addy).address As stno, (addy).streetname As street, (addy).streettypeabbrev As styp, (addy).location As city, (addy).stateabbrev As st,(addy).zip FROM geocode('100 Federal Street, MA', 3, (SELECT ST_Union(the_geom) FROM place WHERE statefp = '25' AND name = 'Lynn')::geometry ) As g; rating | wktlonlat | stno | street | styp | city | st | zip --------+---------------------------+------+---------+------+------+----+------- 7 | POINT(-70.96796 42.4659) | 100 | Federal | St | Lynn | MA | 01905 16 | POINT(-70.96786 42.46853) | NULL | Federal | St | Lynn | MA | 01905 (2 rows) Time: 622.939 ms
Normalize_Address, Pprint_Addy, ST_AsText, ST_SnapToGrid, ST_X, ST_Y