From a427ca3fc94733322a7acf39b22bcc7bdb6ac64f Mon Sep 17 00:00:00 2001
From: Markus Scheidgen <markus.scheidgen@gmail.com>
Date: Tue, 23 Apr 2019 12:21:02 +0200
Subject: [PATCH] Fixed bug with searching multi quantities (atoms,
 quantities).

---
 nomad/api/info.py       |  2 +-
 nomad/datamodel/base.py | 10 +++++-----
 nomad/datamodel/dft.py  |  4 ++--
 nomad/search.py         | 13 ++++++-------
 4 files changed, 14 insertions(+), 15 deletions(-)

diff --git a/nomad/api/info.py b/nomad/api/info.py
index 983636ebf3..35cc9408e8 100644
--- a/nomad/api/info.py
+++ b/nomad/api/info.py
@@ -66,7 +66,7 @@ class InfoResource(Resource):
             'normalizers': [normalizer.__name__ for normalizer in normalizing.normalizers],
             'domain': {
                 'name': datamodel.Domain.instance.name,
-                'quantities': datamodel.Domain.instance.quantities,
+                'quantities': [quantity for quantity in datamodel.Domain.instance.quantities.values()],
                 'metrics_names': datamodel.Domain.instance.metrics_names,
                 'aggregations_names': datamodel.Domain.instance.aggregations_names
             },
diff --git a/nomad/datamodel/base.py b/nomad/datamodel/base.py
index ad8ae4fc7a..dae862ecd2 100644
--- a/nomad/datamodel/base.py
+++ b/nomad/datamodel/base.py
@@ -225,7 +225,7 @@ class Domain:
 
         self.name = name
         self.domain_entry_class = domain_entry_class
-        self.quantities: List[DomainQuantity] = []
+        self.quantities: Dict[str, DomainQuantity] = {}
         self.root_sections = root_sections
 
         reference_domain_calc = domain_entry_class()
@@ -239,13 +239,13 @@ class Domain:
                     quantities[quantity_name] = quantity
                 quantity.name = quantity_name
                 quantity.multi = isinstance(value, list)
-                self.quantities.append(quantity)
+                self.quantities[quantity.name] = quantity
 
         for quantity_name in quantities.keys():
             assert hasattr(reference_domain_calc, quantity_name) and not hasattr(reference_general_calc, quantity_name), \
                 'quantity does not exist or overrides general non domain quantity'
 
-        assert any(quantity.order_default for quantity in Domain.instances[name].quantities), \
+        assert any(quantity.order_default for quantity in Domain.instances[name].quantities.values()), \
             'you need to define a order default quantity'
 
     @property
@@ -255,7 +255,7 @@ class Domain:
         """
         return {
             quantity.metric[0]: (quantity.metric[1], quantity.name)
-            for quantity in self.quantities
+            for quantity in self.quantities.values()
             if quantity.metric is not None
         }
 
@@ -272,7 +272,7 @@ class Domain:
         """
         return {
             quantity.name: quantity.aggregations
-            for quantity in self.quantities
+            for quantity in self.quantities.values()
             if quantity.aggregations > 0
         }
 
diff --git a/nomad/datamodel/dft.py b/nomad/datamodel/dft.py
index 844bc62fb3..0a9c25b591 100644
--- a/nomad/datamodel/dft.py
+++ b/nomad/datamodel/dft.py
@@ -157,7 +157,7 @@ Domain('DFT', DFTCalcWithMetadata, quantities=dict(
     atoms=DomainQuantity(
         'The atom labels of all atoms in the simulated system.',
         # aggregations=len(ase.data.chemical_symbols)),
-        aggregations=200),  # quickfix for bad atom labels
+        aggregations=200, multi=True),  # quickfix for bad atom labels
     basis_set=DomainQuantity(
         'The used basis set functions.', aggregations=10),
     xc_functional=DomainQuantity(
@@ -176,7 +176,7 @@ Domain('DFT', DFTCalcWithMetadata, quantities=dict(
     ),
     quantities=DomainQuantity(
         'All quantities that are used by this calculation',
-        metric=('quantities', 'value_count')
+        metric=('quantities', 'value_count'), multi=True
     ),
     n_total_energies=DomainQuantity(
         'Number of total energy calculations',
diff --git a/nomad/search.py b/nomad/search.py
index 2d0edc4c7a..9dd8aed5e7 100644
--- a/nomad/search.py
+++ b/nomad/search.py
@@ -71,7 +71,7 @@ class Dataset(InnerDoc):
 class WithDomain(IndexMeta):
     """ Override elasticsearch_dsl metaclass to sneak in domain specific mappings """
     def __new__(cls, name, bases, attrs):
-        for quantity in datamodel.Domain.instance.quantities:
+        for quantity in datamodel.Domain.instance.quantities.values():
             attrs[quantity.name] = quantity.elastic_mapping
         return super(WithDomain, cls).__new__(cls, name, bases, attrs)
 
@@ -143,8 +143,8 @@ class Entry(Document, metaclass=WithDomain):
         self.references = [ref.value for ref in source.references]
         self.datasets = [Dataset.from_dataset_popo(ds) for ds in source.datasets]
 
-        for quantity in datamodel.Domain.instance.quantities:
-            setattr(self, quantity.name, getattr(source, quantity.name))
+        for quantity in datamodel.Domain.instance.quantities.keys():
+            setattr(self, quantity, getattr(source, quantity))
 
 
 def delete_upload(upload_id):
@@ -196,7 +196,7 @@ The available search quantities in :func:`aggregate_search` as tuples with *sear
 elastic field and description.
 """
 
-for quantity in datamodel.Domain.instance.quantities:
+for quantity in datamodel.Domain.instance.quantities.values():
     search_spec = ('term', quantity.name, quantity.description)
     search_quantities[quantity.name] = search_spec
 
@@ -218,7 +218,7 @@ metrics_names = list(metric for metric in metrics.keys())
 
 
 order_default_quantity = None
-for quantity in datamodel.Domain.instance.quantities:
+for quantity in datamodel.Domain.instance.quantities.values():
     if quantity.order_default:
         order_default_quantity = quantity.name
 
@@ -243,8 +243,7 @@ def _construct_search(q: Q = None, time_range: Tuple[datetime, datetime] = None,
             values = [value]
 
         for item in values:
-            if key == 'atoms':
-                # TODO This should be configurable and not specific to atoms
+            if datamodel.Domain.instance.quantities[key].multi:
                 items = item.split(',')
             else:
                 items = [item]
-- 
GitLab