implement query sorting (#63)
This commit is contained in:
+32
-1
@@ -351,15 +351,46 @@ class API(object):
|
||||
if k not in reserved_fieldnames and k in p.fields.keys():
|
||||
properties.append((k, v))
|
||||
|
||||
LOGGER.debug('processing sort parameter')
|
||||
val = args.get('sortby')
|
||||
|
||||
if val is not None:
|
||||
sortby = []
|
||||
sorts = val.split(',')
|
||||
for s in sorts:
|
||||
if ':' in s:
|
||||
prop, order = s.split(':')
|
||||
if order not in ['A', 'D']:
|
||||
exception = {
|
||||
'code': 'InvalidParameterValue',
|
||||
'description': 'sort order should be A or D'
|
||||
}
|
||||
LOGGER.error(exception)
|
||||
return headers_, 400, json.dumps(exception)
|
||||
sortby.append({'property': prop, 'order': order})
|
||||
else:
|
||||
sortby.append({'property': s, 'order': 'A'})
|
||||
for s in sortby:
|
||||
if s['property'] not in p.fields.keys():
|
||||
exception = {
|
||||
'code': 'InvalidParameterValue',
|
||||
'description': 'bad sort property'
|
||||
}
|
||||
LOGGER.error(exception)
|
||||
return headers_, 400, json.dumps(exception)
|
||||
else:
|
||||
sortby = []
|
||||
|
||||
LOGGER.debug('Querying provider')
|
||||
LOGGER.debug('startindex: {}'.format(startindex))
|
||||
LOGGER.debug('limit: {}'.format(limit))
|
||||
LOGGER.debug('resulttype: {}'.format(resulttype))
|
||||
LOGGER.debug('sortby: {}'.format(sortby))
|
||||
|
||||
try:
|
||||
content = p.query(startindex=int(startindex), limit=int(limit),
|
||||
resulttype=resulttype, bbox=bbox, time=time,
|
||||
properties=properties)
|
||||
properties=properties, sortby=sortby)
|
||||
except ProviderConnectionError:
|
||||
exception = {
|
||||
'code': 'NoApplicableCode',
|
||||
|
||||
@@ -109,7 +109,7 @@ class CSVProvider(BaseProvider):
|
||||
return feature_collection
|
||||
|
||||
def query(self, startindex=0, limit=10, resulttype='results',
|
||||
bbox=[], time=None, properties=[]):
|
||||
bbox=[], time=None, properties=[], sortby=[]):
|
||||
"""
|
||||
CSV query
|
||||
|
||||
@@ -119,6 +119,7 @@ class CSVProvider(BaseProvider):
|
||||
:param bbox: bounding box [minx,miny,maxx,maxy]
|
||||
:param time: temporal (datestamp or extent)
|
||||
:param properties: list of tuples (name, value)
|
||||
:param sortby: list of dicts (property, order)
|
||||
|
||||
:returns: dict of GeoJSON FeatureCollection
|
||||
"""
|
||||
|
||||
@@ -98,7 +98,7 @@ class ElasticsearchProvider(BaseProvider):
|
||||
return fields_
|
||||
|
||||
def query(self, startindex=0, limit=10, resulttype='results',
|
||||
bbox=[], time=None, properties=[]):
|
||||
bbox=[], time=None, properties=[], sortby=[]):
|
||||
"""
|
||||
query Elasticsearch index
|
||||
|
||||
@@ -108,6 +108,7 @@ class ElasticsearchProvider(BaseProvider):
|
||||
:param bbox: bounding box [minx,miny,maxx,maxy]
|
||||
:param time: temporal (datestamp or extent)
|
||||
:param properties: list of tuples (name, value)
|
||||
:param sortby: list of dicts (property, order)
|
||||
|
||||
:returns: dict of 0..n GeoJSON features
|
||||
"""
|
||||
@@ -181,6 +182,31 @@ class ElasticsearchProvider(BaseProvider):
|
||||
}
|
||||
query['query']['bool']['filter'].append(pf)
|
||||
|
||||
if sortby:
|
||||
LOGGER.debug('processing sortby')
|
||||
query['sort'] = []
|
||||
for sort in sortby:
|
||||
LOGGER.debug('processing sort object: {}'.format(sort))
|
||||
|
||||
sp = sort['property']
|
||||
|
||||
if self.fields[sp]['type'] == 'string':
|
||||
LOGGER.debug('setting ES .raw on property')
|
||||
sort_property = 'properties.{}.raw'.format(sp)
|
||||
else:
|
||||
sort_property = 'properties.{}'.format(sp)
|
||||
|
||||
sort_order = 'asc'
|
||||
if sort['order'] == 'D':
|
||||
sort_order = 'desc'
|
||||
|
||||
sort_ = {
|
||||
sort_property: {
|
||||
'order': sort_order
|
||||
}
|
||||
}
|
||||
query['sort'].append(sort_)
|
||||
|
||||
try:
|
||||
LOGGER.debug('querying Elasticsearch')
|
||||
if startindex + limit > 10000:
|
||||
|
||||
@@ -90,7 +90,7 @@ class GeoJSONProvider(BaseProvider):
|
||||
return data
|
||||
|
||||
def query(self, startindex=0, limit=10, resulttype='results',
|
||||
bbox=[], time=None, properties=[]):
|
||||
bbox=[], time=None, properties=[], sortby=[]):
|
||||
"""
|
||||
query the provider
|
||||
|
||||
@@ -100,6 +100,7 @@ class GeoJSONProvider(BaseProvider):
|
||||
:param bbox: bounding box [minx,miny,maxx,maxy]
|
||||
:param time: temporal (datestamp or extent)
|
||||
:param properties: list of tuples (name, value)
|
||||
:param sortby: list of dicts (property, order)
|
||||
|
||||
:returns: FeatureCollection dict of 0..n GeoJSON features
|
||||
"""
|
||||
|
||||
@@ -185,7 +185,7 @@ class GeoPackageProvider(BaseProvider):
|
||||
self.cursor.execute("SELECT AutoGPKGStop()")
|
||||
|
||||
def query(self, startindex=0, limit=10, resulttype='results',
|
||||
bbox=[], time=None, properties=[]):
|
||||
bbox=[], time=None, properties=[], sortby=[]):
|
||||
"""
|
||||
Query Geopackage for all the content.
|
||||
e,g: http://localhost:5000/collections/poi/items?
|
||||
@@ -197,6 +197,7 @@ class GeoPackageProvider(BaseProvider):
|
||||
:param bbox: bounding box [minx,miny,maxx,maxy]
|
||||
:param time: temporal (datestamp or extent)
|
||||
:param properties: list of tuples (name, value)
|
||||
:param sortby: list of dicts (property, order)
|
||||
|
||||
:returns: GeoJSON FeaturesCollection
|
||||
"""
|
||||
|
||||
@@ -156,7 +156,7 @@ class PostgreSQLProvider(BaseProvider):
|
||||
LOGGER.debug('Table:{}'.format(self.table))
|
||||
|
||||
def query(self, startindex=0, limit=10, resulttype='results',
|
||||
bbox=[], time=None, properties=[]):
|
||||
bbox=[], time=None, properties=[], sortby=[]):
|
||||
"""
|
||||
Query Postgis for all the content.
|
||||
e,g: http://localhost:5000/collections/hotosm_bdi_waterways/items?
|
||||
@@ -168,6 +168,7 @@ class PostgreSQLProvider(BaseProvider):
|
||||
:param bbox: bounding box [minx,miny,maxx,maxy]
|
||||
:param time: temporal (datestamp or extent)
|
||||
:param properties: list of tuples (name, value)
|
||||
:param sortby: list of dicts (property, order)
|
||||
|
||||
:returns: GeoJSON FeaturesCollection
|
||||
"""
|
||||
|
||||
@@ -151,7 +151,7 @@ class SQLiteProvider(BaseProvider):
|
||||
return cursor
|
||||
|
||||
def query(self, startindex=0, limit=10, resulttype='results',
|
||||
bbox=[], time=None, properties=[]):
|
||||
bbox=[], time=None, properties=[], sortby=[]):
|
||||
"""
|
||||
Query Sqlite for all the content.
|
||||
e,g: http://localhost:5000/collections/countries/items?
|
||||
@@ -163,6 +163,7 @@ class SQLiteProvider(BaseProvider):
|
||||
:param bbox: bounding box [minx,miny,maxx,maxy]
|
||||
:param time: temporal (datestamp or extent)
|
||||
:param properties: list of tuples (name, value)
|
||||
:param sortby: list of dicts (property, order)
|
||||
|
||||
:returns: GeoJSON FeaturesCollection
|
||||
"""
|
||||
|
||||
@@ -52,6 +52,18 @@ settings = {
|
||||
'properties': {
|
||||
'geometry': {
|
||||
'type': 'geo_shape'
|
||||
},
|
||||
'properties': {
|
||||
'properties': {
|
||||
'nameascii': {
|
||||
'type': 'text',
|
||||
'fields': {
|
||||
'raw': {
|
||||
'type': 'keyword'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,18 @@ def test_query(config):
|
||||
assert len(results['features']) == 1
|
||||
assert results['features'][0]['ID'] == 1559804
|
||||
|
||||
results = p.query(sortby=[{'property': 'nameascii', 'order': 'A'}])
|
||||
assert results['features'][0]['properties']['nameascii'] == 'Abidjan'
|
||||
|
||||
results = p.query(sortby=[{'property': 'nameascii', 'order': 'D'}])
|
||||
assert results['features'][0]['properties']['nameascii'] == 'Zagreb'
|
||||
|
||||
results = p.query(sortby=[{'property': 'scalerank', 'order': 'A'}])
|
||||
assert results['features'][0]['properties']['scalerank'] == 0
|
||||
|
||||
results = p.query(sortby=[{'property': 'scalerank', 'order': 'D'}])
|
||||
assert results['features'][0]['properties']['scalerank'] == 8
|
||||
|
||||
|
||||
def test_get(config):
|
||||
p = ElasticsearchProvider(config)
|
||||
|
||||
Reference in New Issue
Block a user