README.md in geocoder-1.4.4 vs README.md in geocoder-1.4.5
- old
+ new
@@ -112,10 +112,14 @@
Geocoder will print warnings if you exceed the rate limit for your geocoding service. Some services — Google notably — enforce a per-second limit in addition to a per-day limit. To avoid exceeding the per-second limit, you can add a `SLEEP` option to pause between requests for a given amount of time. You can also load objects in batches to save memory, for example:
rake geocode:all CLASS=YourModel SLEEP=0.25 BATCH=100
+To avoid per-day limit issues (for example if you are trying to geocode thousands of objects and don't want to reach the limit), you can add a `LIMIT` option. Warning: This will ignore the `BATCH` value if provided.
+
+ rake geocode:all CLASS=YourModel LIMIT=1000
+
### Avoiding Unnecessary API Requests
Geocoding only needs to be performed under certain conditions. To avoid unnecessary work (and quota usage) you will probably want to geocode an object only when:
* an address is present
@@ -174,15 +178,15 @@
Some utility methods are also available:
# look up coordinates of some location (like searching Google Maps)
Geocoder.coordinates("25 Main St, Cooperstown, NY")
=> [42.700149, -74.922767]
-
+
# distance between Eiffel Tower and Empire State Building
Geocoder::Calculations.distance_between([47.858205,2.294359], [40.748433,-73.985655])
=> 3619.77359999382 # in configured units (default miles)
-
+
# find the geographic center (aka center of gravity) of objects or points
Geocoder::Calculations.geographic_center([city1, city2, [40.22,-73.99], city4])
=> [35.14968, -90.048929]
Please see the code for more methods and detailed information about arguments (eg, working with kilometers).
@@ -331,33 +335,33 @@
Some common configuration options are:
# config/initializers/geocoder.rb
Geocoder.configure(
-
+
# geocoding service (see below for supported options):
:lookup => :yandex,
-
+
# IP address geocoding service (see below for supported options):
:ip_lookup => :maxmind,
-
+
# to use an API key:
:api_key => "...",
-
+
# geocoding service request timeout, in seconds (default 3):
:timeout => 5,
-
+
# set default units to kilometers:
:units => :km,
-
+
# caching (see below for details):
:cache => Redis.new,
:cache_prefix => "..."
-
+
)
-Please see `lib/geocoder/configuration.rb` for a complete list of configuration options. Additionally, some lookups have their own configuration options, some of which are directly supported by Geocoder. For example, to specify a value for Google's `bounds` parameter:
+Please see [`lib/geocoder/configuration.rb`](https://github.com/alexreisner/geocoder/blob/master/lib/geocoder/configuration.rb) for a complete list of configuration options. Additionally, some lookups have their own configuration options, some of which are directly supported by Geocoder. For example, to specify a value for Google's `bounds` parameter:
# with Google:
Geocoder.search("Paris", :bounds => [[32.1,-95.9], [33.9,-94.3]])
Please see the [source code for each lookup](https://github.com/alexreisner/geocoder/tree/master/lib/geocoder/lookups) to learn about directly supported parameters. Parameters which are not directly supported can be specified using the `:params` option, by which you can pass arbitrary parameters to any geocoding service. For example, to use Nominatim's `countrycodes` parameter:
@@ -367,31 +371,45 @@
Or, to search within a particular region with Google:
Geocoder.search("...", :params => {:region => "..."})
-You can also configure multiple geocoding services at once, like this:
+Or, to use parameters in your model:
+ class Venue
+
+ # build an address from street, city, and state attributes
+ geocoded_by :address_from_components, :params => {:region => "..."}
+
+ # store the fetched address in the full_address attribute
+ reverse_geocoded_by :latitude, :longitude, :address => :full_address, :params => {:region => "..."}
+ end
+
+
+### Configure Multiple Services
+
+You can configure multiple geocoding services at once, like this:
+
Geocoder.configure(
:timeout => 2,
:cache => Redis.new,
-
+
:yandex => {
:api_key => "...",
:timeout => 5
},
-
+
:baidu => {
:api_key => "..."
},
-
+
:maxmind => {
:api_key => "...",
:service => :omni
}
-
+
)
The above combines global and service-specific options and could be useful if you specify different geocoding services for different models or under different conditions. Lookup-specific settings override global settings. In the above example, the timeout for all lookups would be 2 seconds, except for Yandex which would be 5.
@@ -405,11 +423,13 @@
* **Key signup**: https://console.developers.google.com/flows/enableapi?apiid=geocoding_backend&keyType=SERVER_SIDE
* **Quota**: 2,500 requests/24 hrs, 5 requests/second
* **Region**: world
* **SSL support**: yes (required if key is used)
* **Languages**: see https://developers.google.com/maps/faq#languagesupport
-* **Extra options**: `:bounds` - pass SW and NE coordinates as an array of two arrays to bias results towards a viewport
+* **Extra params**:
+ * `:bounds` - pass SW and NE coordinates as an array of two arrays to bias results towards a viewport
+ * `:google_place_id` - pass `true` if search query is a Google Place ID
* **Documentation**: https://developers.google.com/maps/documentation/geocoding/intro
* **Terms of Service**: http://code.google.com/apis/maps/terms.html#section_10_12
* **Limitations**: "You must not use or display the Content without a corresponding Google map, unless you are explicitly permitted to do so in the Maps APIs Documentation, or through written permission from Google." "You must not pre-fetch, cache, or store any Content, except that you may store: (i) limited amounts of Content for the purpose of improving the performance of your Maps API Implementation..."
#### Google Maps API for Work (`:google_premier`)
@@ -461,26 +481,38 @@
* **Languages**: ?
* **Documentation**: http://wiki.openstreetmap.org/wiki/Nominatim
* **Terms of Service**: http://wiki.openstreetmap.org/wiki/Nominatim_usage_policy
* **Limitations**: Please limit request rate to 1 per second and include your contact information in User-Agent headers (eg: `Geocoder.configure(:http_headers => { "User-Agent" => "your contact info" })`). [Data licensed under Open Database License (ODbL) (you must provide attribution).](http://www.openstreetmap.org/copyright)
+#### PickPoint (`:pickpoint`)
+
+* **API key**: required
+* **Key signup**: [https://pickpoint.io](https://pickpoint.io)
+* **Quota**: 2500 requests / day for free non-commercial usage, commercial plans are [available](https://pickpoint.io/#pricing). No rate limit.
+* **Region**: world
+* **SSL support**: required
+* **Languages**: worldwide
+* **Documentation**: [https://pickpoint.io/api-reference](https://pickpoint.io/api-reference)
+* **Limitations**: [Data licensed under Open Database License (ODbL) (you must provide attribution).](http://www.openstreetmap.org/copyright)
+
+
#### LocationIQ (`:location_iq`)
* **API key**: required
-* **Quota**: 6 request/second (30k req/day), then ability to purchase more
+* **Quota**: 60 requests/minute (2 req/sec, 10k req/day), then [ability to purchase more](http://locationiq.org/#pricing)
* **Region**: world
* **SSL support**: yes
* **Languages**: ?
-* **Documentation**: http://locationiq.org/#docs
+* **Documentation**: https://locationiq.org/#docs
* **Terms of Service**: https://unwiredlabs.com/tos
-* **Limitations**: [Data licensed under Open Database License (ODbL) (you must provide attribution).](http://www.openstreetmap.org/copyright)
+* **Limitations**: [Data licensed under Open Database License (ODbL) (you must provide attribution).](https://www.openstreetmap.org/copyright)
#### OpenCageData (`:opencagedata`)
* **API key**: required
* **Key signup**: http://geocoder.opencagedata.com
-* **Quota**: 2500 requests / day, then ability to purchase more (free during beta)
+* **Quota**: 2500 requests / day, then [ability to purchase more](https://geocoder.opencagedata.com/pricing)
* **Region**: world
* **SSL support**: yes
* **Languages**: worldwide
* **Documentation**: http://geocoder.opencagedata.com/api.html
* **Limitations**: [Data licensed under Open Database License (ODbL) (you must provide attribution).](http://www.openstreetmap.org/copyright)
@@ -505,31 +537,25 @@
* **Languages**: English
* **Documentation**: ?
* **Terms of Service**: http://geocoder.ca/?terms=1
* **Limitations**: "Under no circumstances can our data be re-distributed or re-sold by anyone to other parties without our written permission."
-#### Geocoder.us (`:geocoder_us`)
-
-* **API key**: HTTP Basic Auth
-* **Sign up**: http://geocoder.us/user/signup
-* **Quota**: You can purchase 20,000 credits at a time for $50
-* **Region**: US
-* **SSL support**: no
-* **Languages**: English
-* **Documentation**: http://geocoder.us/help/
-* **Terms of Service**: http://geocoder.us/terms.shtml
-* **Limitations**: ?
-
#### Mapbox (`:mapbox`)
* **API key**: required
* **Dataset**: Uses `mapbox.places` dataset by default. Specify the `mapbox.places-permanent` dataset by setting: `Geocoder.configure(:mapbox => {:dataset => "mapbox.places-permanent"})`
* **Key signup**: https://www.mapbox.com/pricing/
* **Quota**: depends on plan
* **Region**: complete coverage of US and Canada, partial coverage elsewhere (see for details: https://www.mapbox.com/developers/api/geocoding/#coverage)
* **SSL support**: yes
* **Languages**: English
+* **Extra params** (see Mapbox docs for more):
+ * `:country` - restrict results to a specific country, e.g., `us` or `ca`
+ * `:types` - restrict results to categories such as `address`,
+ `neighborhood`, `postcode`
+ * `:proximity` - bias results toward a `lng,lat`, e.g.,
+ `params: { proximity: "-84.0,42.5" }`
* **Documentation**: https://www.mapbox.com/developers/api/geocoding/
* **Terms of Service**: https://www.mapbox.com/tos/
* **Limitations**: For `mapbox.places` dataset, must be displayed on a Mapbox map; Cache results for up to 30 days. For `mapbox.places-permanent` dataset, depends on plan.
* **Notes**: Currently in public beta.
@@ -583,37 +609,37 @@
* **Notes**: You can specify which projection you want to use by setting, for example: `Geocoder.configure(:esri => {:outSR => 102100})`. If you will store results, set the flag and provide API key: `Geocoder.configure(:esri => {:api_key => ["client_id", "client_secret"], :for_storage => true})`. If you want to, you can also supply an ESRI token directly: `Geocoder.configure(:esri => {:token => Geocoder::EsriToken.new('TOKEN', Time.now + 1.day})`
#### Mapzen (`:mapzen`)
* **API key**: required
-* **Quota**: 6/sec, up to 30k per day, paid plan info at https://mapzen.com/documentation/search/api-keys-rate-limits/#rate-limits
+* **Quota**: 25,000 free requests/month and [ability to purchase more](https://mapzen.com/pricing/)
* **Region**: world
* **SSL support**: yes
-* **Languages**: en
+* **Languages**: en; see https://mapzen.com/documentation/search/language-codes/
* **Documentation**: https://mapzen.com/documentation/search/search/
* **Terms of Service**: http://mapzen.com/terms
-* **Limitations**: ?
+* **Limitations**: [You must provide attribution](https://mapzen.com/rights/)
* **Notes**: Mapzen is the primary author of Pelias and offers Pelias-as-a-service in free and paid versions https://mapzen.com/pelias.
#### Pelias (`:pelias`)
-* **API key**: required
+* **API key**: configurable (self-hosted service)
* **Quota**: none (self-hosted service)
* **Region**: world
* **SSL support**: yes
-* **Languages**: en
-* **Documentation**: https://mapzen.com/documentation/search/search/
-* **Terms of Service**: http://mapzen.com/terms
+* **Languages**: en; see https://mapzen.com/documentation/search/language-codes/
+* **Documentation**: http://pelias.io/
+* **Terms of Service**: http://pelias.io/data_licenses.html
* **Limitations**: See terms
* **Notes**: Configure your self-hosted pelias with the `endpoint` option: `Geocoder.configure(:lookup => :pelias, :api_key => 'your_api_key', :pelias => {:endpoint => 'self.hosted/pelias'})`. Defaults to `localhost`.
#### Data Science Toolkit (`:dstk`)
Data Science Toolkit provides an API whose response format is like Google's but which can be set up as a privately hosted service.
* **API key**: none
-* **Quota**: None quota if you are self-hosting the service.
+* **Quota**: No quota if you are self-hosting the service.
* **Region**: world
* **SSL support**: ?
* **Languages**: en
* **Documentation**: http://www.datasciencetoolkit.org/developerdocs
* **Terms of Service**: http://www.datasciencetoolkit.org/developerdocs#googlestylegeocoder
@@ -633,22 +659,22 @@
* **Notes**: To use Baidu set `Geocoder.configure(:lookup => :baidu, :api_key => "your_api_key")`.
#### Geocodio (`:geocodio`)
* **API key**: required
-* **Quota**: 2,500 free requests/day then purchase $.001 for each, also has volume pricing and plans
+* **Quota**: 2,500 free requests/day then purchase $0.0005 for each, also has volume pricing and plans.
* **Region**: US
* **SSL support**: yes
* **Languages**: en
* **Documentation**: http://geocod.io/docs
* **Terms of Service**: http://geocod.io/terms-of-use
* **Limitations**: No restrictions on use
#### SmartyStreets (`:smarty_streets`)
* **API key**: requires auth_id and auth_token (set `Geocoder.configure(:api_key => [id, token])`)
-* **Quota**: 10,000 free, 250/month then purchase at sliding scale.
+* **Quota**: 250/month then purchase at sliding scale.
* **Region**: US
* **SSL support**: yes (required)
* **Languages**: en
* **Documentation**: http://smartystreets.com/kb/liveaddress-api/rest-endpoint
* **Terms of Service**: http://smartystreets.com/legal/terms-of-service
@@ -728,11 +754,11 @@
### IP Address Services
#### FreeGeoIP (`:freegeoip`)
* **API key**: none
-* **Quota**: 10000 requests per hour. After reaching the hourly quota, all of your requests will result in HTTP 403 (Forbidden) until it clears up on the next roll over.
+* **Quota**: 15,000 requests per hour. After reaching the hourly quota, all of your requests will result in HTTP 403 (Forbidden) until it clears up on the next roll over.
* **Region**: world
* **SSL support**: no
* **Languages**: English
* **Documentation**: http://github.com/fiorix/freegeoip/blob/master/README.md
* **Terms of Service**: ?
@@ -759,12 +785,13 @@
* **SSL support**: yes
* **Languages**: English
* **Documentation**: https://market.mashape.com/fcambus/telize
* **Terms of Service**: ?
* **Limitations**: ?
-* **Notes**: To use Telize set `Geocoder.configure(:ip_lookup => :telize, :api_key => "your_api_key")`.
+* **Notes**: To use Telize set `Geocoder.configure(:ip_lookup => :telize, :api_key => "your_api_key")`. Or configure your self-hosted telize with the `host` option: `Geocoder.configure(:ip_lookup => :telize, :telize => {:host => "localhost"})`.
+
#### MaxMind Legacy Web Services (`:maxmind`)
* **API key**: required
* **Quota**: Request Packs can be purchased
* **Region**: world
@@ -817,10 +844,20 @@
* **SSL support**: no (not without access key - see https://signup.ip-api.com/)
* **Languages**: English
* **Documentation**: http://ip-api.com/docs/
* **Terms of Service**: https://signup.ip-api.com/terms
+#### DB-IP.com (`:db_ip_com`)
+
+* **API key**: required
+* **Quota**: 2,500/day (with free API Key, 50,000/day and up for paid API keys)
+* **Region**: world
+* **SSL support**: yes (with paid API keys - see https://db-ip.com/api/)
+* **Languages**: English (English with free API key, multiple languages with paid API keys)
+* **Documentation**: https://db-ip.com/api/doc.php
+* **Terms of Service**: https://db-ip.com/tos.php
+
### IP Address Local Database Services
#### MaxMind Local (`:maxmind_local`) - EXPERIMENTAL
This lookup provides methods for geocoding IP addresses without making a call to a remote API (improves speed and availability). It works, but support is new and should not be considered production-ready. Please [report any bugs](https://github.com/alexreisner/geocoder/issues) you encounter.
@@ -845,11 +882,11 @@
You can generate ActiveRecord migrations and download and import data via provided rake tasks:
# generate migration to create tables
rails generate geocoder:maxmind:geolite_city
-
+
# download, unpack, and import data
rake geocoder:maxmind:geolite:load PACKAGE=city
You can replace `city` with `country` in any of the above tasks, generators, and configurations.
@@ -934,11 +971,11 @@
class Venue
# build an address from street, city, and state attributes
geocoded_by :address_from_components
-
+
# store the fetched address in the full_address attribute
reverse_geocoded_by :latitude, :longitude, :address => :full_address
end
However, there can be only one set of latitude/longitude attributes, and whichever you specify last will be used. For example:
@@ -946,11 +983,11 @@
class Venue
geocoded_by :address,
:latitude => :fetched_latitude, # this will be overridden by the below
:longitude => :fetched_longitude # same here
-
+
reverse_geocoded_by :latitude, :longitude
end
We don't want ambiguity when doing distance calculations -- we need a single, authoritative source for coordinates!
@@ -974,11 +1011,11 @@
class Venue
after_validation :reverse_geocode, :if => :has_coordinates
after_validation :geocode, :if => :has_location, :unless => :has_coordinates
-
+
end
Use Outside of Rails
--------------------
@@ -997,30 +1034,28 @@
Geocoder.configure(:lookup => :test)
Geocoder::Lookup::Test.add_stub(
"New York, NY", [
{
- 'latitude' => 40.7143528,
- 'longitude' => -74.0059731,
+ 'coordinates' => [40.7143528, -74.0059731],
'address' => 'New York, NY, USA',
'state' => 'New York',
'state_code' => 'NY',
'country' => 'United States',
'country_code' => 'US'
}
]
)
-Now, any time Geocoder looks up "New York, NY" its results array will contain one result with the above attributes. You can also set a default stub, to be returned when no other stub is found for a given query:
+Now, any time Geocoder looks up "New York, NY" its results array will contain one result with the above attributes. Note each lookup requires an exact match to the text you provide as the first argument. The above example would, therefore, not match a request for "New York, NY, USA" and a second stub would need to be created to match that particular request. You can also set a default stub, to be returned when no other stub is found for a given query:
Geocoder.configure(:lookup => :test)
Geocoder::Lookup::Test.set_default_stub(
[
{
- 'latitude' => 40.7143528,
- 'longitude' => -74.0059731,
+ 'coordinates' => [40.7143528, -74.0059731],
'address' => 'New York, NY, USA',
'state' => 'New York',
'state_code' => 'NY',
'country' => 'United States',
'country_code' => 'US'
@@ -1195,25 +1230,31 @@
When reporting an issue, please list the version of Geocoder you are using and any relevant information about your application (Rails version, database type and version, etc). Also avoid vague language like "it doesn't work." Please describe as specifically as you can what behavior you are actually seeing (eg: an error message? a nil return value?).
Please DO NOT use GitHub issues to ask questions about how to use Geocoder. Sites like [StackOverflow](http://www.stackoverflow.com/) are a better forum for such discussions.
-### Known Issue
+### Known Issues
+#### Using `near` with `includes`
+
You cannot use the `near` scope with another scope that provides an `includes` option because the `SELECT` clause generated by `near` will overwrite it (or vice versa).
Instead of using `includes` to reduce the number of database queries, try using `joins` with either the `:select` option or a call to `preload`. For example:
# Pass a :select option to the near scope to get the columns you want.
# Instead of City.near(...).includes(:venues), try:
City.near("Omaha, NE", 20, :select => "cities.*, venues.*").joins(:venues)
-
+
# This preload call will normally trigger two queries regardless of the
# number of results; one query on hotels, and one query on administrators.
# Instead of Hotel.near(...).includes(:administrator), try:
Hotel.near("London, UK", 50).joins(:administrator).preload(:administrator)
If anyone has a more elegant solution to this problem I am very interested in seeing it.
+
+#### Using `near` with objects close to the 180th meridian
+
+The `near` method will not look across the 180th meridian to find objects close to a given point. In practice this is rarely an issue outside of New Zealand and certain surrounding islands. This problem does not exist with the zero-meridian. The problem is due to a shortcoming of the Haversine formula which Geocoder uses to calculate distances.
Contributing
------------