Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/azure maps #1667

Merged
merged 10 commits into from
Dec 4, 2024
13 changes: 13 additions & 0 deletions README_API_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,19 @@ Global Street Address Lookups
```
* Via environment variables and other external methods. See **Setting AWS Credentials** in the [AWS SDK for Ruby Developer Guide](https://docs.aws.amazon.com/sdk-for-ruby/v3/developer-guide/setup-config.html).

### Azure (`:azure`)

* **API key**: required (set `Geocoder.configure(lookup: :azure, api_key: "your_api_key", limit: your_limit)`)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The info in parentheses is duplicated below. Let's remove it here.

* **Key signup**: https://azure.microsoft.com/en-us/products/azure-maps
* **Quota**: 5,000 request/month with free API key, more with paid keys (see https://azure.microsoft.com/en-us/pricing/details/azure-maps)
* **Region**: world
* **SSL support**: yes
* **Languages**: see https://learn.microsoft.com/en-us/azure/azure-maps/supported-languages
* **Documentation**: https://learn.microsoft.com/en-us/azure/azure-maps
* **Terms of Service**: https://azure.microsoft.com/en-us/support/legal
* **Limitations**: Azure Maps doesn't have any maximum daily limits on the number of requests that can be made, however there are limits to the maximum number of queries per second (QPS) (see https://learn.microsoft.com/en-us/azure/azure-maps/azure-maps-qps-rate-limits)
* **Notes**: To use Azure, set `Geocoder.configure(lookup: :azure, api_key: "your_api_key", limit: your_limit)` :limit - restrict the maximum amount of returned results, e.g. limit: 10.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two things:

  1. Let's fix the syntax, showing that :limit has to be specified in an azure: {...} hash.
  2. This makes it sound like :limit is required, which it isn't,, so let's specify the default (10) and mention that it's optional.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updated README_API_GUIDE.md, sorry I forgot to update it yesterday.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No worries, thanks!


### Bing (`:bing`)

* **API key**: required (set `Geocoder.configure(lookup: :bing, api_key: key)`)
Expand Down
1 change: 1 addition & 0 deletions lib/geocoder/lookup.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def all_services_with_http_requests
def street_services
@street_services ||= [
:location_iq,
:azure,
:esri,
:google,
:google_premier,
Expand Down
56 changes: 56 additions & 0 deletions lib/geocoder/lookups/azure.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
require 'geocoder/lookups/base'
require 'geocoder/results/azure'

module Geocoder::Lookup
class Azure < Base
def name
'Azure'
end

def required_api_key_parts
['api_key']
end

def supported_protocols
[:https]
end

private

def base_query_url(query)
host = 'atlas.microsoft.com/search/address'

if query.reverse_geocode?
"#{protocol}://#{host}/reverse/json?"
else
"#{protocol}://#{host}/json?"
end
end

def query_url_params(query)
params = {
'api-version' => 1.0,
'language' => query.options[:language] || 'en',
'limit' => configuration[:limit] || 10,
'query' => query.sanitized_text,
'subscription-key' => configuration.api_key
}

params.merge(super)
end

def results(query)
return [] unless (doc = fetch_data(query))

return doc if doc['error']

if doc['results']&.any?
doc['results']
elsif doc['addresses']&.any?
doc['addresses']
else
[]
end
end
end
end
65 changes: 65 additions & 0 deletions lib/geocoder/results/azure.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
require 'geocoder/results/base'

module Geocoder::Result
class Azure < Base
def address
@data['address']['freeformAddress']
end

def building_number
@data['address']['buildingNumber']
end

def city
@data['address']['municipality']
end

def coordinates
if @data['position'].is_a?(String) # reverse geocoding result
@data['position'].split(',').map(&:to_f)
elsif @data['position'].is_a?(Hash) # forward geocoding result
[@data['position']['lat'], @data['position']['lon']]
end
end

def country
@data['address']['country']
end

def country_code
@data['address']['countryCode']
end

def district
@data['address']['municipalitySubdivision']
end

def postal_code
@data['address']['postalCode']
end

def province
@data['address']['countrySubdivision']
end

def state
@data['address']['countrySubdivision']
end

def state_code
@data['address']['countrySubdivisionCode']
end

def street_name
@data['address']['streetName']
end

def street_number
@data['address']['streetNumber']
end

def viewport
@data['viewport'] || {}
end
end
end
8 changes: 8 additions & 0 deletions test/fixtures/azure_invalid_key
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"error": {
"code": "InvalidKey",
"message": "The provided key was incorrect or the account resource does not exist.",
"target": "WWW-Authenticate",
"details": []
}
}
57 changes: 57 additions & 0 deletions test/fixtures/azure_jakarta
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"summary": {
"query": "Jakarta",
"queryType": "NON_NEAR",
"queryTime": 66,
"numResults": 1,
"offset": 0,
"totalResults": 10,
"fuzzyLevel": 1
},
"results": [
{
"type": "Geography",
"id": "6AhgONQ49YLQy9Ku_ocHcA",
"score": 1,
"entityType": "Municipality",
"matchConfidence": {
"score": 1
},
"address": {
"municipality": "Jakarta",
"countrySubdivision": "Jakarta",
"countrySubdivisionName": "Jakarta",
"countrySubdivisionCode": "JK",
"countryCode": "ID",
"country": "Indonesia",
"countryCodeISO3": "IDN",
"freeformAddress": "Jakarta, Jakarta"
},
"position": {
"lat": -6.17476,
"lon": 106.82707
},
"viewport": {
"topLeftPoint": {
"lat": -5.95462, "lon": 106.68588
},
"btmRightPoint": {
"lat": -6.37083, "lon": 106.9729
}
},
"boundingBox": {
"topLeftPoint": {
"lat": -5.95462, "lon": 106.68588
},
"btmRightPoint": {
"lat": -6.37083, "lon": 106.9729
}
},
"dataSources": {
"geometry": {
"id": "00004944-3100-3c00-0000-000023c347ee"
}
}
}
]
}
50 changes: 50 additions & 0 deletions test/fixtures/azure_madison_square_garden
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"summary": {
"query": "madison square garden",
"queryType": "NON_NEAR",
"queryTime": 89,
"numResults": 1,
"offset": 0,
"totalResults": 6,
"fuzzyLevel": 1
},
"results": [
{
"type": "Street",
"id": "QyS-HWGa0fkjABCOcS09Rw",
"score": 0.8939382576343416,
"matchConfidence": {
"score": 0.8939382576343416
},
"address": {
"streetName": "Garten Place",
"municipality": "Madison Heights",
"countrySecondarySubdivision": "Amherst",
"countrySubdivision": "VA",
"countrySubdivisionName": "Virginia",
"countrySubdivisionCode": "VA",
"postalCode": "24572",
"extendedPostalCode": "24572-4418, 24572-4419",
"countryCode": "US",
"country": "United States",
"countryCodeISO3": "USA",
"freeformAddress": "Garten Place, Madison Heights, VA 24572",
"localName": "Madison Heights"
},
"position": {
"lat": 37.484629,
"lon": -79.109597
},
"viewport": {
"topLeftPoint": {
"lat": 37.485,
"lon": -79.11055
},
"btmRightPoint": {
"lat": 37.48439,
"lon": -79.10872
}
}
}
]
}
12 changes: 12 additions & 0 deletions test/fixtures/azure_no_results
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"summary": {
"query": "Jakarta",
"queryType": "NON_NEAR",
"queryTime": 66,
"numResults": 0,
"offset": 0,
"totalResults": 0,
"fuzzyLevel": 1
},
"results": []
}
36 changes: 36 additions & 0 deletions test/fixtures/azure_reverse
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"summary": {
"queryTime": 12,
"numResults": 1
},
"addresses": [
{
"address": {
"buildingNumber": "10",
"streetNumber": "10",
"routeNumbers": [],
"street": "Jalan Mohammad Husni Thamrin",
"streetName": "Jalan Mohammad Husni Thamrin",
"streetNameAndNumber": "Jalan Mohammad Husni Thamrin 10",
"countryCode": "ID",
"countrySubdivision": "DKI Jakarta",
"municipality": "Jakarta",
"postalCode": "10230",
"municipalitySecondarySubdivision": "Menteng",
"country": "Indonesia",
"countryCodeISO3": "IDN",
"freeformAddress": "Jalan Mohammad Husni Thamrin 10, Kecamatan Jakarta, DKI Jakarta 10230",
"boundingBox": {
"northEast": "-6.198818,106.823264",
"southWest": "-6.199555,106.823246",
"entity": "position"
},
"countrySubdivisionName": "DKI Jakarta",
"countrySubdivisionCode": "JK",
"localName": "Jakarta"
},
"position": "-6.199203,106.823082",
"id": "hlyQM4iHOYn16mWumCtnJA"
}
]
}
Loading
Loading