At 08:20 AM 2/25/2009, pgsql-sql-ow...@postgresql.org wrote:
To: pgsql-sql@postgresql.org
From:  Mark Stosberg <m...@summersault.com>
Subject: Best practices for geo-spatial city name searches?
Date:  Tue, 24 Feb 2009 11:19:56 -0500
Message-ID:  <20090224111956.5b7a4...@summersault.com>
X-Archive-Number: 200902/94
X-Sequence-Number: 32231

Hello,

I use PostgreSQL and the "cube" type to perform geo-spatial zipcode proximity searches. I'm wondering about the best practices also supporting a geo-spatial
distance search based on a city name rather than zipcode.

In our original data model, we used a 'zipcodes' table, with the zipcode as the primary key. This can of course contain a "City Name" column, but there is a problem with this, illustrated a "Nome, Alaska" case. Nome's zipcode is 99762.
It maps to multiple cities including Diomede, Alaska and Nome, Alaska.

In the data model described, only the "Diomede" row is imported, and the other rows, including the "Nome, Alaska" row are dropped. So if you try to search
for Nome, Alaska, you won't find anything.

One solution would be to have a "cities" table, with the city/state as the primary key, and a zipcode as an additional column. Then, by joining on the
zipcodes table, the coordinates for a city could be found.

Is there any other way I should be considering data modelling to support
searches on zipcodes and cities?

Hi Mark,

I built a very similar system for www.hutz.com. It uses a complete postcode database, without dropping nearby/overlapping cities. It also includes the postcode "alias" values, which are names that the post office uses as "equivalent" to the official names.

Within the city table, I created a series of self-joining id's:

id|alias_city_id|post_code_city_id|muni_city_id

So a city record can be an "alias", "postcode" or "muni" record. A muni record is the definitive record for a city (and is defined by the postcode record closest to the city center as defined by the USGS). A postcode record, represents a postcode (zipcode) region within a city. An alias represents an alternate name that either refers to a muni record or a postcode record (and is defined as "alias_city_id IS NOT NULL")

So if I want to search the table for only muni city records, the query looks like

select * from city where id = muni_city_id

I also included lat/long coordinates for every record, making it easy to calculate distances and find all city records within a certain range, etc. (I used the "point" and "circle" operators for this along with a GiST index - it's not perfect for long distances - it assumes the earth is flat, but it works great for small distances and is very fast).

I hope this helps. Feel free to contact me on-list or off, if you want to discuss more.

Steve


--
Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-sql

Reply via email to