add skip_geometry to remaining feature providers (#887)

* skip geometry for SQLite/GPKG backends (#886)

* simplify GKPG

* add for remaining providers, add to doc
This commit is contained in:
Tom Kralidis
2022-04-19 13:44:56 -04:00
committed by GitHub
parent 36b88e0719
commit 356fe1280c
7 changed files with 52 additions and 20 deletions
@@ -15,17 +15,17 @@ pygeoapi core feature providers are listed below, along with a matrix of support
parameters.
.. csv-table::
:header: Provider, property filters/display, resulttype, bbox, datetime, sortby, CQL
:header: Provider, property filters/display, resulttype, bbox, datetime, sortby, skipGeometry, CQL
:align: left
CSV,✅/✅,results/hits,❌,❌,❌,❌
Elasticsearch,✅/✅,results/hits,✅,✅,✅,✅
GeoJSON,✅/✅,results/hits,❌,❌,❌,❌
MongoDB,✅/❌,results,✅,✅,✅,❌
OGR,✅/❌,results/hits,✅,❌,❌,❌
PostgreSQL,✅/✅,results/hits,✅,❌,✅,❌
SQLiteGPKG,✅/❌,results/hits,✅,❌,❌,❌
SensorThingsAPI,✅/✅,results/hits,✅,✅,✅,❌
CSV,✅/✅,results/hits,❌,❌,❌,✅,
Elasticsearch,✅/✅,results/hits,✅,✅,✅,✅,✅
GeoJSON,✅/✅,results/hits,❌,❌,❌,✅,
MongoDB,✅/❌,results,✅,✅,✅,✅,
OGR,✅/❌,results/hits,✅,❌,❌,✅,
PostgreSQL,✅/✅,results/hits,✅,❌,✅,✅,
SQLiteGPKG,✅/❌,results/hits,✅,❌,❌,✅,
SensorThingsAPI,✅/✅,results/hits,✅,✅,✅,✅,
Below are specific connection examples based on supported providers.
+7 -5
View File
@@ -81,7 +81,8 @@ class MongoProvider(BaseProvider):
map, reduce, "myresults")
return result.distinct('_id')
def _get_feature_list(self, filterObj, sortList=[], skip=0, maxitems=1):
def _get_feature_list(self, filterObj, sortList=[], skip=0, maxitems=1,
skip_geometry=False):
featurecursor = self.featuredb[self.collection].find(filterObj)
if sortList:
@@ -93,6 +94,8 @@ class MongoProvider(BaseProvider):
featurelist = list(featurecursor)
for item in featurelist:
item['id'] = str(item.pop('_id'))
if skip_geometry:
item['geometry'] = None
return featurelist, matchCount
@@ -126,10 +129,9 @@ class MongoProvider(BaseProvider):
ASCENDING if (sort['order'] == '+') else DESCENDING)
for sort in sortby]
featurelist, matchcount = self._get_feature_list(filterobj,
sortList=sort_list,
skip=offset,
maxitems=limit)
featurelist, matchcount = self._get_feature_list(
filterobj, sortList=sort_list, skip=offset, maxitems=limit,
skip_geometry=skip_geometry)
if resulttype == 'hits':
featurelist = []
+8 -4
View File
@@ -353,7 +353,8 @@ class OGRProvider(BaseProvider):
result = self._response_feature_hits(layer)
elif resulttype == 'results':
LOGGER.debug('results specified')
result = self._response_feature_collection(layer, limit)
result = self._response_feature_collection(
layer, limit, skip_geometry=skip_geometry)
else:
LOGGER.error('Invalid resulttype: %s' % resulttype)
@@ -455,13 +456,15 @@ class OGRProvider(BaseProvider):
LOGGER.error(self.gdal.GetLastErrorMsg())
raise gdalerr
def _ogr_feature_to_json(self, ogr_feature):
def _ogr_feature_to_json(self, ogr_feature, skip_geometry=False):
geom = ogr_feature.GetGeometryRef()
if self.transform_out:
# Optionally reproject the geometry
geom.Transform(self.transform_out)
json_feature = ogr_feature.ExportToJson(as_object=True)
if skip_geometry:
json_feature['geometry'] = None
try:
json_feature['id'] = json_feature['properties'].pop(self.id_field)
except Exception as err:
@@ -470,7 +473,7 @@ class OGRProvider(BaseProvider):
return json_feature
def _response_feature_collection(self, layer, limit):
def _response_feature_collection(self, layer, limit, skip_geometry=False):
"""
Assembles output from Layer query as
GeoJSON FeatureCollection structure.
@@ -492,7 +495,8 @@ class OGRProvider(BaseProvider):
ogr_feature = _ignore_gdal_error(layer, 'GetNextFeature')
count = 0
while ogr_feature is not None:
json_feature = self._ogr_feature_to_json(ogr_feature)
json_feature = self._ogr_feature_to_json(
ogr_feature, skip_geometry=skip_geometry)
feature_collection['features'].append(json_feature)
+6 -2
View File
@@ -128,11 +128,12 @@ class SQLiteGPKGProvider(BaseProvider):
# WHERE continent=? <class 'tuple'>: ('Europe',)
return where_clause, where_values
def __response_feature(self, row_data):
def __response_feature(self, row_data, skip_geometry=False):
"""
Assembles GeoJSON output from DB query
:param row_data: DB row result
:param skip_geometry: whether to skip geometry (default False)
:returns: `dict` of GeoJSON Feature
"""
@@ -145,6 +146,9 @@ class SQLiteGPKGProvider(BaseProvider):
feature["geometry"] = json.loads(
rd.pop('AsGeoJSON({})'.format(self.geom_col))
)
if skip_geometry:
feature["geometry"] = None
feature['properties'] = rd
feature['id'] = feature['properties'].pop(self.id_field)
@@ -306,7 +310,7 @@ class SQLiteGPKGProvider(BaseProvider):
for rd in row_data:
feature_collection['features'].append(
self.__response_feature(rd))
self.__response_feature(rd, skip_geometry=skip_geometry))
return feature_collection
+4
View File
@@ -96,6 +96,10 @@ def test_query(config):
assert len(results['features'][0]['properties']) == 37
results = p.query(skip_geometry=True)
for feature in results['features']:
assert feature['geometry'] is None
def test_get(config):
p = MongoProvider(config)
+9
View File
@@ -174,3 +174,12 @@ def test_query_with_property_vsicurl(config_vsicurl_csv):
assert len(features) == 10
for feature in features:
assert 'Lazio' in feature['properties']['denominazione_regione']
def test_query_with_skip_geometry_vsicurl(config_vsicurl_csv):
"""Testing query for a valid JSON object with property filter"""
p = OGRProvider(config_vsicurl_csv)
feature_collection = p.query(skip_geometry=True)
for feature in feature_collection['features']:
assert feature['geometry'] is None
+9
View File
@@ -167,3 +167,12 @@ def test_get_geopackage_not_existing_item_raise_exception(config_geopackage):
p = SQLiteGPKGProvider(config_geopackage)
with pytest.raises(ProviderItemNotFoundError):
p.get(-1)
def test_get_geopackage_skip_geometry(config_geopackage):
"""Testing query for skipped geometry"""
p = SQLiteGPKGProvider(config_geopackage)
feature_collection = p.query(skip_geometry=True)
for feature in feature_collection['features']:
assert feature['geomtry'] is None