diff --git a/gui/src/components/api.js b/gui/src/components/api.js index 3d4019b54ab72aaa7f17e19b3bbc919b977a2d04..9305c2f4325a3abe7978db9e89d405bc6f8e170c 100644 --- a/gui/src/components/api.js +++ b/gui/src/components/api.js @@ -207,6 +207,8 @@ class Api { this.onStartLoading = () => null this.onFinishLoading = () => null + this.statistics = {} + this._swaggerClient = Swagger(`${apiBase}/swagger.json`) this.keycloak = keycloak @@ -389,6 +391,29 @@ class Api { ...search})) .catch(handleApiError) .then(response => response.body) + .then(response => { + // fill absent statistics values with values from prior searches + // this helps to keep consistent values, e.g. in the metadata search view + if (response.statistics) { + const empty = {} + Object.keys(response.statistics.total.all).forEach(metric => empty[metric] = 0) + Object.keys(response.statistics) + .filter(key => !['total', 'authors', 'atoms'].includes(key)) + .forEach(key => { + if (!this.statistics[key]) { + this.statistics[key] = new Set() + } + const values = this.statistics[key] + Object.keys(response.statistics[key]).forEach(value => values.add(value)) + values.forEach(value => { + if (!response.statistics[key][value]) { + response.statistics[key][value] = empty + } + }) + }) + } + return response + }) .finally(this.onFinishLoading) } diff --git a/nomad/datamodel/base.py b/nomad/datamodel/base.py index c49716feb71e715de4c585efd513fd39ccd11041..88e76268ad207345539ed1bf2950fa014d64a281 100644 --- a/nomad/datamodel/base.py +++ b/nomad/datamodel/base.py @@ -193,8 +193,6 @@ class DomainQuantity: 0 (the default) means no aggregations. metric: Indicates that this quantity should be used as search metric. Values need to be tuples with metric name and elastic aggregation (e.g. sum, cardinality) - zero_aggs: Return aggregation values for values with zero hits in the search. Default - is with zero aggregations. elastic_mapping: An optional elasticsearch_dsl mapping. Default is ``Keyword``. elastic_search_type: An optional elasticsearch search type. Default is ``term``. elastic_field: An optional elasticsearch key. Default is the name of the quantity. @@ -206,8 +204,7 @@ class DomainQuantity: def __init__( self, description: str = None, multi: bool = False, aggregations: int = 0, order_default: bool = False, metric: Tuple[str, str] = None, - zero_aggs: bool = True, metadata_field: str = None, - elastic_mapping: type = None, + metadata_field: str = None, elastic_mapping: type = None, elastic_search_type: str = 'term', elastic_field: str = None, elastic_value: Callable[[Any], Any] = None, argparse_action: str = 'append'): @@ -218,7 +215,6 @@ class DomainQuantity: self.order_default = order_default self.aggregations = aggregations self.metric = metric - self.zero_aggs = zero_aggs self.elastic_mapping = elastic_mapping self.elastic_search_type = elastic_search_type self.metadata_field = metadata_field diff --git a/nomad/datamodel/dft.py b/nomad/datamodel/dft.py index d2ca7cb930638b5175f4d98a6f4697ad15cc99a1..c1d9f85d3411352bcacae62762c99e920ba8c218 100644 --- a/nomad/datamodel/dft.py +++ b/nomad/datamodel/dft.py @@ -274,7 +274,7 @@ Domain( order_default=True), atoms=DomainQuantity( 'The atom labels of all atoms in the simulated system.', - aggregations=len(ase.data.chemical_symbols), multi=True, zero_aggs=False), + aggregations=len(ase.data.chemical_symbols), multi=True), only_atoms=DomainQuantity( 'The atom labels concatenated in species-number order. Used with keyword search ' 'to facilitate exclusive searches.', diff --git a/nomad/search.py b/nomad/search.py index 39cdbe45275c209bb1f58cc0c0837e85d556a5c9..a913775b46b601c139c3b97e51db2124b8368290 100644 --- a/nomad/search.py +++ b/nomad/search.py @@ -440,10 +440,7 @@ class SearchRequest: The basic doc_count metric ``code_runs`` is always given. """ quantity = quantities[quantity_name] - min_doc_count = 0 if quantity.zero_aggs else 1 - terms = A( - 'terms', field=quantity.elastic_field, size=size, min_doc_count=min_doc_count, - order=dict(_key='asc')) + terms = A('terms', field=quantity.elastic_field, size=size, order=dict(_key='asc')) buckets = self._search.aggs.bucket('statistics:%s' % quantity_name, terms) self._add_metrics(buckets, metrics_to_use)