Name

Geocode — 주소를 스트링(또는 다른 정규화된 주소)으로 입력받아 NAD83 경위도로 투영된 포인트 도형, 각 주소에 대한 정규화된 주소 및 순위를 포함하는 가능성 있는 위치들의 집합을 출력합니다. 순위가 낮을수록 주소와 위치가 일치할 가능성이 커집니다. 결과를 순위가 낮은 순서로 정렬합니다. 결과의 최대 개수(기본값 10) 및 restrict_region(기본값 NULL) 옵션 파라미터를 넘겨줄 수 있습니다.

Synopsis

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);

설명

주소를 스트링(또는 다른 정규화된 주소)으로 입력받아 NAD83 경위도로 투영된 포인트 도형, 각 주소에 대한 normalized_address (addy) 및 순위를 포함하는 가능성 있는 위치들의 집합을 출력합니다. 순위가 낮을수록 주소와 위치가 일치할 가능성이 커집니다. 결과를 순위가 낮은 순서로 정렬합니다. TIGER 데이터(edge, face, addr), PostgreSQL 퍼지 문자열 매칭(soundex, levenshtein), 그리고 PostGIS 라인 보간 함수를 이용해서 TIGER 경계선을 따라 주소를 보간합니다. 순위가 높을수록 지오코딩 작업이 올바를 가능성이 떨어집니다. 지오코딩된 포인트는 기본적으로 중심선에서 도로 주소가 위치한 쪽(왼쪽/오른쪽)으로 10미터 오프셋됩니다.

개선 사항: 2.0.0 버전에서 TIGER 2010 데이터 구조를 지원하고, 속도와 지오코딩 작업의 정확도를 향상시키기 위해 몇몇 로직을 수정하고, 포인트를 중심선에서 도로 주소가 위치한 쪽으로 오프셋시키기 시작했습니다. 새로 도입된 max_results 파라미터는 결과의 개수를 설정하거나 최선의 결과만 반환하도록 하는 데 유용합니다.

기본 예시

매사추세츠(MA), 미네소타(MN), 캘리포니아(CA), 로드아일랜드(RI) 주의 TIGER 데이터를 로드한 PostgreSQL 9.1rc1/PostGIS 2.0이 실행되고 있는 3.0 GHZ 단일 프로세서 및 2GB 램 윈도우7 컴퓨터에서 다음 예시를 실행시키는 데 걸리는 시간을 측정했습니다.

완전 일치를 계산하는 것이 더 빠릅니다(61밀리초).

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
    

주소들을 지오코딩하는 데 배치(batch) 작업을 이용합니다. 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