Skip to content

Commit

Permalink
Get all nested fields in Elasticsearch (#1882)
Browse files Browse the repository at this point in the history
* Get all nested fields in Elasticsearch

When using the Elasticsearch provider for a collection, the only queryables returned are the first-level properties of its features. With this change, all nested properties are returned as fields and it's possible to filter items using those nested properties (e.g. /items?prop1.prop2=example )

* Remove whitespace from blank lines

* Fix indentation
  • Loading branch information
Mafaldarc authored Dec 22, 2024
1 parent 88bfa5f commit 125a1b4
Showing 1 changed file with 28 additions and 12 deletions.
40 changes: 28 additions & 12 deletions pygeoapi/provider/elasticsearch_.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,20 +119,36 @@ def get_fields(self):
LOGGER.warning('could not get fields; returning empty set')
return {}

for k, v in p['properties'].items():
if 'type' in v:
if v['type'] == 'text':
self._fields[k] = {'type': 'string'}
elif v['type'] == 'date':
self._fields[k] = {'type': 'string', 'format': 'date'}
elif v['type'] in ('float', 'long'):
self._fields[k] = {'type': 'number',
'format': v['type']}
else:
self._fields[k] = {'type': v['type']}

self._fields = self.get_nested_fields(p, self._fields)
return self._fields

def get_nested_fields(self, properties, fields, prev_field=None):
"""
Get Elasticsearch fields (names, types) for all nested properties
:param properties: `dict` of Elasticsearch mappings properties
:param fields: `dict` of fields in the current iteration
:param prev_field: name of the parent field
:returns: dict of fields
"""
for k, v in properties['properties'].items():

cur_field = k if prev_field is None else f'{prev_field}.{k}'

if isinstance(v, dict) and 'properties' in v:
fields = self.get_nested_fields(v, fields, cur_field)
else:
if v['type'] == 'text':
fields[cur_field] = {'type': 'string'}
elif v['type'] == 'date':
fields[cur_field] = {'type': 'string', 'format': 'date'}
elif v['type'] in ('float', 'long'):
fields[cur_field] = {'type': 'number', 'format': v['type']}
else:
fields[cur_field] = {'type': v['type']}
return fields

@crs_transform
def query(self, offset=0, limit=10, resulttype='results',
bbox=[], datetime_=None, properties=[], sortby=[],
Expand Down

0 comments on commit 125a1b4

Please sign in to comment.