Skip to content

Commit cc12eed

Browse files
committed
feat: implement optional count for postgresql provider
This work has been done to allow the result count to be enabled or disabled for the PostgreSQL provider. By disabling the count you can get improved performance on large datasets but on smaller datasets this is unlikely to have any affect.
1 parent e20d7d1 commit cc12eed

3 files changed

Lines changed: 78 additions & 7 deletions

File tree

docs/source/publishing/ogcapi-features.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,7 @@ Must have PostGIS installed.
625625
id_field: osm_id
626626
table: hotosm_bdi_waterways
627627
geom_field: foo_geom
628+
count: true # Optional; Default true; Enable/disable count for improved performance.
628629
629630
A number of database connection options can be also configured in the provider in order to adjust properly the sqlalchemy engine client.
630631
These are optional and if not specified, the default from the engine will be used. Please see also `SQLAlchemy docs <https://docs.sqlalchemy.org/en/14/core/engines.html#custom-dbapi-connect-arguments-on-connect-routines>`_.
@@ -662,6 +663,7 @@ These are optional and if not specified, the default from the engine will be use
662663
id_field: osm_id
663664
table: hotosm_bdi_waterways
664665
geom_field: foo_geom
666+
count: true # Optional; Default true; Enable/disable count for improved performance.
665667
666668
The PostgreSQL provider is also able to connect to Cloud SQL databases.
667669

@@ -677,6 +679,7 @@ The PostgreSQL provider is also able to connect to Cloud SQL databases.
677679
password: postgres
678680
id_field: id
679681
table: states
682+
count: true # Optional; Default true; Enable/disable count for improved performance.
680683
681684
This is what a configuration for `Google Cloud SQL`_ connection looks like. The ``host``
682685
block contains the necessary socket connection information.

pygeoapi/provider/sql.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ def __init__(
128128
self.id_field = provider_def['id_field']
129129
self.geom = provider_def.get('geom_field', 'geom')
130130
self.driver_name = driver_name
131-
self.count = str2bool(provider_def.get('count', True))
131+
self.count = str(provider_def.get('count', 'true')).lower() == 'true'
132132

133133
LOGGER.debug(f'Name: {self.name}')
134134
LOGGER.debug(f'Table: {self.table}')
@@ -214,18 +214,18 @@ def query(
214214
.options(selected_properties)
215215
)
216216

217-
matched = results.count()
218-
219-
LOGGER.debug(f'Found {matched} result(s)')
220-
221217
LOGGER.debug('Preparing response')
222218
response = {
223219
'type': 'FeatureCollection',
224220
'features': [],
225-
'numberMatched': matched,
226221
'numberReturned': 0
227222
}
228223

224+
if self.count or resulttype == 'hits':
225+
matched = results.count()
226+
response['numberMatched'] = matched
227+
LOGGER.debug(f'Found {matched} result(s)')
228+
229229
if resulttype == 'hits' or not results:
230230
return response
231231

tests/provider/test_postgresql_provider.py

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ def config():
8585
},
8686
'id_field': 'osm_id',
8787
'table': 'hotosm_bdi_waterways',
88-
'geom_field': 'foo_geom'
88+
'geom_field': 'foo_geom',
89+
'count': 'true'
8990
}
9091

9192

@@ -908,3 +909,70 @@ def test_transaction_create_handles_invalid_input_data(pg_api_, data):
908909
headers, code, content = manage_collection_item(
909910
pg_api_, req, action='create', dataset='hot_osm_waterways')
910911
assert 'generic error' in content
912+
913+
914+
def test_provider_count_default_value(config):
915+
# Arrange
916+
provider = PostgreSQLProvider(config)
917+
918+
# Act
919+
results = provider.query()
920+
921+
# Assert
922+
assert results['numberMatched'] == 14776
923+
924+
925+
@pytest.mark.parametrize("count_value", [
926+
('true'),
927+
('TRUE')
928+
])
929+
def test_provider_count_true(config, count_value):
930+
# Arrange
931+
config['count'] = count_value
932+
provider = PostgreSQLProvider(config)
933+
934+
# Act
935+
results = provider.query()
936+
937+
# Assert
938+
assert results['numberMatched'] == 14776
939+
940+
941+
@pytest.mark.parametrize("count_value", [
942+
('false'),
943+
('FALSE')
944+
])
945+
def test_provider_count_false(config, count_value):
946+
# Arrange
947+
config['count'] = count_value
948+
provider = PostgreSQLProvider(config)
949+
950+
# Act
951+
results = provider.query()
952+
953+
# Assert
954+
assert 'numberMatched' not in results
955+
956+
957+
def test_provider_count_false_with_resulttype_hits(config):
958+
# Arrange
959+
config['count'] = 'false'
960+
provider = PostgreSQLProvider(config)
961+
962+
# Act
963+
results = provider.query(resulttype="hits")
964+
965+
# Assert
966+
assert results['numberMatched'] == 14776
967+
968+
969+
def test_provider_count_number_string(config):
970+
# Arrange
971+
config['count'] = '1'
972+
provider = PostgreSQLProvider(config)
973+
974+
# Act
975+
results = provider.query()
976+
977+
# Assert
978+
assert 'numberMatched' not in results

0 commit comments

Comments
 (0)