This document discusses using PostGIS to build location-aware applications. PostGIS extends PostgreSQL with spatial datatypes and functions to store and query geographic data. It allows querying data based on proximity and spatial relationships. The speaker provides examples of storing bear location data with PostGIS and querying to find bears within park boundaries or the number of bears in multiple parks. PostGIS enables building scalable location-aware applications and APIs.
1 of 37
Downloaded 56 times
More Related Content
PostGIS on Rails
1. PostGIS on Rails
Matt Nemenman
matt@apartmentlist.com
@quarterdome
Friday, April 19, 1
2. About me
Programmer
Love maps
Building map based rental search
engine @ Apartment List
Friday, April 19, 2
4. Where am I?
Latitude and Longitude
HTML5 geolocation or GPS
Address
Geocoding
Reverse geocoding
Friday, April 19, 4
5. Where am I?
What if you need to know ...
Neighborhood
School district
National park
Earthquake safety zone
Friday, April 19, 5
6. What is around me?
Yelp and Google Places API
Restaurants, bars, etc.
Points of interest
Friday, April 19, 6
7. What is around me?
What if you want to know ...
What are three neighborhoods
closest to me?
Average rent for 1 bedroom in
Lower Pacific Heights
Crime rate on my city block
Who is around me?
Friday, April 19, 7
8. When 3rd party APIs
fall short ...
Get your own data set
Build your own solution
Friday, April 19, 8
9. Spatial Systems
MongoDB
Solr
MySQL
Oracle / DB2
PostGIS
Friday, April 19, 9
10. PostGIS
Geospatial extension to Postgres
New datatypes
Functions to work with those
datatypes
Spatial indices using GiST
create extension postgis;
Friday, April 19, 10
12. A simple example
Yosemite Park Ranger
Tracking bears equipped with GPS
transmitters
Want to show all the bears on Google
Maps
Friday, April 19, 12
13. Bears (database
migration)
create_table :bears do |t|
t.column :lat, :float
t.column :lon, :float
end
add_index :bears, :lat
add_index :bears, :lon
add_index :bears, [:lat, :lon]
Friday, April 19, 13
14. Bears (model)
class Bear < ActiveRecord::Base
def self.bbox(sw_lon, sw_lat,
ne_lon, ne_lat)
self
.where( :lon => sw_lon..ne_lon )
.where( :lat => sw_lat..ne_lat )
end
end
Friday, April 19, 14
15. A PostGIS example
(migration)
create_table :bears do |t|
t.column :coordinates,
:geometry,
:srid => 4326
end
add_index :bears,
:coordinates,
:spatial => true
Friday, April 19, 15
16. A PostGIS example
(model)
def self.box(sw_lon, sw_lat, ne_lon, ne_lat)
factory = Rails.application.spatial_factory
sw = factory.point(sw_lon, sw_lat)
nw = factory.point(sw_lon, ne_lat)
ne = factory.point(ne_lon, ne_lat)
se = factory.point(ne_lon, sw_lat)
ring = factory.linear_ring([sw, nw, ne, se])
bbox = factory.polygon(ring)
self
.where('ST_Intersects(coordinates, :bbox)',
:bbox => bbox)
end
Friday, April 19, 16
17. A PostGIS example
1_000_000.times do
Bear.create!( ...)
end
Friday, April 19, 17
18. 1,000,000 bears
PostGIS is 1.5x to 50x faster
Friday, April 19, 18
19. Active Record
PostGIS Adapter
Migration support
Automatic conversion of PostGIS
datatypes to Ruby (RGeo) objects and
back
gem 'pg'
gem 'rgeo'
gem 'activerecord-postgis-adapter'
Friday, April 19, 19
24. More examples
# d parks
Column | Type
------------------------+-----------------------------
id | integer
name | character varying(255)
boundary | geometry(Geometry,4326)
Indexes:
"parks_pkey" PRIMARY KEY, btree (id)
"index_parks_on_name" btree (name)
"index_parks_on_boundary" gist (polygon)
# select id, name, boundary from parks limit 2;
id | name | boundary
--------+-------------+------------------------
1 | Yosemite |0103000020E6100000010000...
2 | Yellowstone |0103000020E6100000010000...
Friday, April 19, 24
25. How many bears are
in Yosemite now?
##> park = Park.find_by_name(Yosemite)
##> bears = Bear.where(ST_Intersects(coordinates, :bounds),
:bounds => park.boundary)
##> bear_count = bears.count
Friday, April 19, 25
26. How Many Bears in
Yosemite and Yellowstone
(Ruby)?
##> yosemite = Park.find_by_name(Yosemite)
##> yellowstone = Park.find_by_name(Yellowstone)
##> bounds = yosemite.boundary + yellowstone.boundary
##> bears = Bear.where(ST_Intersects(coordinates, :bounds),
:bounds => bounds)
##> bear_count = bears.count
Friday, April 19, 26
27. How Many Bears in
Yosemite and Yellowstone
(SQL)?
select count(*) from bears
inner join parks
on ST_Intersects(bears.coordinates,
parks.boundary)
where parks.name in (Yosemite,
Yellowstone);
Friday, April 19, 27
28. Three parks closest
to me?
Distance operator (KNN) is a feature
of Postgres 9.1 and above
select id, name,
boundary <-> ST_Point(37.775, -122.44) as distance
from parks
order by distance
limit 3;
Friday, April 19, 28
33. Do Try It at Home
Heroku Postgres
https://devcenter.heroku.com/articles/heroku-
postgres-extensions-postgis-full-text-search
Postgres.app
http://postgresapp.com/
select postgis_full_version();
Friday, April 19, 33
34. Data Sources
(free)
US Census Data (Tiger)
http://www.census.gov/geo/maps-data/data/tiger.html
Zillow Neighborhoods
http://www.zillow.com/howto/api/neighborhood-
boundaries.htm
Friday, April 19, 34
35. Data Sources
(commercial)
Maponics
http://www.maponics.com/
Urban Mapping
http://www.urbanmapping.com/
Onboard Informatics
http://www.onboardinformatics.com/
Friday, April 19, 35
36. Links
PostGIS
http://postgis.net/
Active Record PostGIS Adapter
https://github.com/dazuma/
activerecord-postgis-adapter
RGeo
https://github.com/dazuma/rgeo
Friday, April 19, 36
37. Q & A
We are hiring @apartmentlist!
Friday, April 19, 37