Relevance metadata for Mapbox

This commit is contained in:
Juan Ignacio Sánchez Lara
2018-07-11 07:42:21 +02:00
parent 2af9204542
commit 825e3b7ee8
3 changed files with 68 additions and 37 deletions

View File

@@ -29,15 +29,10 @@ class MapboxBulkGeocoder(MapboxGeocoder, StreetPointBulkGeocoder):
for search in searches:
elements = self._encoded_elements(search)
self._logger.debug('--> Sending serial search: {}'.format(search))
coordinates = self._geocode_search(*elements)
results.append((search[0], coordinates, []))
return results
result = self.geocode_meta(*elements)
def _geocode_search(self, address, city, state, country):
coordinates = self.geocode(searchtext=address, city=city,
state_province=state, country=country)
self._logger.debug('--> result sent')
return coordinates
results.append((search[0], result[0], result[1]))
return results
def _encoded_elements(self, search):
(search_id, address, city, state, country) = search
@@ -58,11 +53,11 @@ class MapboxBulkGeocoder(MapboxGeocoder, StreetPointBulkGeocoder):
frees.append(free)
self._logger.debug('--> sending free search: {}'.format(frees))
xy_results = self.geocode_free_text(frees)
full_results = self.geocode_free_text_meta(frees)
results = []
self._logger.debug('--> searches: {}; xy: {}'.format(searches, xy_results))
for s, r in zip(searches, xy_results):
results.append((s[0], r, []))
self._logger.debug('--> searches: {}; xy: {}'.format(searches, full_results))
for s, r in zip(searches, full_results):
results.append((s[0], r[0], r[1]))
self._logger.debug('--> results: {}'.format(results))
return results

View File

@@ -22,6 +22,8 @@ ENTRY_COORDINATES = 'coordinates'
ENTRY_TYPE = 'type'
TYPE_POINT = 'Point'
EMPTY_RESPONSE = [[], {}]
class MapboxGeocoder(Traceable):
'''
@@ -49,12 +51,16 @@ class MapboxGeocoder(Traceable):
for a_json_response in json_response:
if a_json_response[ENTRY_FEATURES]:
feature = a_json_response[ENTRY_FEATURES][0]
result.append(self._extract_lng_lat_from_feature(feature))
result.append([
self._extract_lng_lat_from_feature(feature),
self._extract_metadata_from_result(feature)
]
)
else:
result.append([])
result.append(EMPTY_RESPONSE)
return result
else:
return []
return EMPTY_RESPONSE
def _extract_lng_lat_from_feature(self, feature):
geometry = feature[ENTRY_GEOMETRY]
@@ -67,6 +73,14 @@ class MapboxGeocoder(Traceable):
latitude = location[1]
return [longitude, latitude]
def _extract_metadata_from_result(self, result):
return {
'relevance': self._normalize_relevance(float(result['relevance']))
}
def _normalize_relevance(self, relevance):
return 1 if relevance == 0.99 else relevance
def _validate_input(self, searchtext, city=None, state_province=None,
country=None):
if searchtext and searchtext.strip():
@@ -88,8 +102,13 @@ class MapboxGeocoder(Traceable):
:param country: Country ISO 3166 code
:return: [x, y] on success, [] on error
"""
return self.geocode_meta(searchtext, city, state_province, country)[0]
@qps_retry(qps=10)
def geocode_meta(self, searchtext, city=None, state_province=None,
country=None):
if not self._validate_input(searchtext, city, state_province, country):
return []
return EMPTY_RESPONSE
address = []
if searchtext and searchtext.strip():
@@ -99,32 +118,31 @@ class MapboxGeocoder(Traceable):
if state_province:
address.append(normalize(state_province))
country = [country] if country else None
free_search = ', '.join(address)
return self.geocode_free_text([free_search], country)[0]
return self.geocode_free_text_meta([free_search], country)[0]
@qps_retry(qps=10)
def geocode_free_text(self, free_searches, country=None):
def geocode_free_text_meta(self, free_searches, country=None):
"""
:param free_searches: Free text searches
:param country: Country ISO 3166 code
:return: list of [x, y] on success, [] on error
"""
country = [country] if country else None
try:
free_search = ';'.join([self._escape(fs) for fs in free_searches])
self._logger.debug('--> free search: {}'.format(free_search))
self._logger.debug('--> free search: {}, country: {}'.format(free_search, country))
response = self._geocoder.forward(address=free_search.decode('utf-8'),
country=country,
limit=1)
country=country)
if response.status_code == requests.codes.ok:
return self._parse_geocoder_response(response.text)
elif response.status_code == requests.codes.bad_request:
return []
return EMPTY_RESPONSE
elif response.status_code == requests.codes.unprocessable_entity:
return []
return EMPTY_RESPONSE
else:
raise ServiceException(response.status_code, response)
except requests.Timeout as te:
@@ -138,7 +156,7 @@ class MapboxGeocoder(Traceable):
# Don't raise the exception to continue with the geocoding job
self._logger.error('Error connecting to Mapbox geocoding server',
exception=ce)
return []
return EMPTY_RESPONSE
def _escape(self, free_search):
# Semicolon is used to separate batch geocoding; there's no documented